Files
allwpilib/hal/lib/Athena/Task.cpp
James Kuszmaul 0b7bb41b22 This commit adds JNI bindings for the C++ Notifier.
The bindings only wrap the HAL interface, rather than the entire C++ Notifier,
as I ran into issues trying to wrap the whole Notifier (all the existing
bindings only wrap HAL components, so wrapping stuff in :wpilibc is
unexplored). As such, the new edu.wpi.first.wpilibj.Notifier is just a
re-implementation of the wpilibc/.../Notifier.cpp.

The purpose of doing this bindings is to allow Java users a better option
for running tasks which require good timing (such as control loops). The
previous method used java.util.Timer to schedule a task, causing various
issues. Although this update does improve things, Java loop timing is still
substantially worse than that of C++, and, even worse, if Java decides to call
the garbage collector at the wrong time then the loop can be delayed by
multiple milliseconds and the next iteration will be shorter to account for it
(although this particular behavior could be updated).

A few notes on individual components:
-the HAL Task.hpp and Task.cpp were modified due to compilation/linkage
 issues with the JNI bindings. Nothing substantive changed.
-NotifierJNI was added to the build files for gradle.
-HALUtil was modified to include a function for getting the length of a C
 pointer, rather than relying on it being 32-bit.

Change-Id: I966512d8a82c2a438ed8c8bbcc6cdc6ed186d0f2
2015-06-02 16:05:03 -04:00

92 lines
2.3 KiB
C++

#include "HAL/Task.hpp"
#include <stdio.h>
#include <signal.h>
struct TaskArgs {
FUNCPTR fun;
char* name;
pthread_t** task;
uint32_t arg0, arg1, arg2, arg3, arg4,
arg5, arg6, arg7, arg8, arg9;
};
void* startRoutine(void* data) {
TaskArgs* args = (TaskArgs*) data;
printf("[HAL] Starting task %s...\n", args->name);
int val = args->fun(args->arg0, args->arg1, args->arg2, args->arg3, args->arg4,
args->arg5, args->arg6, args->arg7, args->arg8, args->arg9);
printf("[HAL] Exited task %s with code %i\n", args->name, val);
*args->task = NULL;
int* ret = new int(); *ret = val;
return ret;
}
TASK spawnTask(char * name, int priority, int options, int stackSize,
FUNCPTR entryPt, uint32_t arg0, uint32_t arg1, uint32_t arg2,
uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6,
uint32_t arg7, uint32_t arg8, uint32_t arg9) {
printf("[HAL] Spawning task %s...\n", name);
pthread_t* task = new pthread_t;
pthread_attr_t* attr = new pthread_attr_t;
pthread_attr_init(attr);
TaskArgs* args = new TaskArgs();
args->fun = entryPt;
args->name = name;
args->task = new pthread_t*;
*args->task = task;
args->arg0 = arg0; args->arg1 = arg1; args->arg2 = arg2; args->arg3 = arg3; args->arg4 = arg4;
args->arg5 = arg5; args->arg6 = arg6; args->arg7 = arg7; args->arg8 = arg8; args->arg9 = arg9;
if (pthread_create(task, attr, startRoutine, args) == 0) {
printf("[HAL] Success\n");
pthread_detach(*task);
} else {
printf("[HAL] Failure\n");
task = NULL;
}
pthread_attr_destroy(attr);
return task;
}
STATUS restartTask(TASK task) {
return ERROR; // TODO: implement;
}
STATUS deleteTask(TASK task) {
return ERROR; // TODO: implement
}
STATUS isTaskReady(TASK task) {
return ERROR; // TODO: implement
}
STATUS isTaskSuspended(TASK task) {
return ERROR; // TODO: implement
}
STATUS suspendTask(TASK task) {
return ERROR; // TODO: implement
}
STATUS resumeTask(TASK task) {
return ERROR; // TODO: implement
}
STATUS verifyTaskID(TASK task) {
if (task != NULL && pthread_kill(*task, 0) == 0) {
return OK;
} else {
return ERROR;
}
}
STATUS setTaskPriority(TASK task, int priority) {
return ERROR; // TODO: implement
}
STATUS getTaskPriority(TASK task, int* priority) {
return ERROR; // TODO: implement
}