AP_Scripting: Support libraries holding the scheduler lock

This commit is contained in:
Michael du Breuil 2020-02-11 16:11:11 -07:00 committed by Andrew Tridgell
parent c257cea375
commit a0bfc823b3
3 changed files with 43 additions and 15 deletions

View File

@ -144,6 +144,7 @@ singleton GCS method set_message_interval MAV_RESULT'enum uint8_t 0 MAVLINK_COMM
include AP_Vehicle/AP_Vehicle.h include AP_Vehicle/AP_Vehicle.h
singleton AP_Vehicle alias vehicle singleton AP_Vehicle alias vehicle
singleton AP_Vehicle scheduler-semaphore
singleton AP_Vehicle method set_mode boolean uint8_t 0 UINT8_MAX ModeReason::SCRIPTING'literal singleton AP_Vehicle method set_mode boolean uint8_t 0 UINT8_MAX ModeReason::SCRIPTING'literal
singleton AP_Vehicle method get_mode uint8_t singleton AP_Vehicle method get_mode uint8_t
singleton AP_Vehicle method get_likely_flying boolean singleton AP_Vehicle method get_likely_flying boolean

View File

@ -7,20 +7,21 @@
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
char keyword_alias[] = "alias"; char keyword_alias[] = "alias";
char keyword_ap_object[] = "ap_object"; char keyword_ap_object[] = "ap_object";
char keyword_comment[] = "--"; char keyword_comment[] = "--";
char keyword_depends[] = "depends"; char keyword_depends[] = "depends";
char keyword_enum[] = "enum"; char keyword_enum[] = "enum";
char keyword_field[] = "field"; char keyword_field[] = "field";
char keyword_include[] = "include"; char keyword_include[] = "include";
char keyword_method[] = "method"; char keyword_method[] = "method";
char keyword_operator[] = "operator"; char keyword_operator[] = "operator";
char keyword_read[] = "read"; char keyword_read[] = "read";
char keyword_semaphore[] = "semaphore"; char keyword_scheduler_semaphore[] = "scheduler-semaphore";
char keyword_singleton[] = "singleton"; char keyword_semaphore[] = "semaphore";
char keyword_userdata[] = "userdata"; char keyword_singleton[] = "singleton";
char keyword_write[] = "write"; char keyword_userdata[] = "userdata";
char keyword_write[] = "write";
// attributes (should include the leading ' ) // attributes (should include the leading ' )
char keyword_attr_enum[] = "'enum"; char keyword_attr_enum[] = "'enum";
@ -298,7 +299,8 @@ struct userdata_field {
}; };
enum userdata_flags { enum userdata_flags {
UD_FLAG_SEMAPHORE = (1U << 0), UD_FLAG_SEMAPHORE = (1U << 0),
UD_FLAG_SCHEDULER_SEMAPHORE = (1U << 1),
}; };
struct userdata_enum { struct userdata_enum {
@ -788,6 +790,8 @@ void handle_singleton(void) {
} else if (strcmp(type, keyword_semaphore) == 0) { } else if (strcmp(type, keyword_semaphore) == 0) {
node->flags |= UD_FLAG_SEMAPHORE; node->flags |= UD_FLAG_SEMAPHORE;
} else if (strcmp(type, keyword_scheduler_semaphore) == 0) {
node->flags |= UD_FLAG_SCHEDULER_SEMAPHORE;
} else if (strcmp(type, keyword_method) == 0) { } else if (strcmp(type, keyword_method) == 0) {
handle_method(node->name, &(node->methods)); handle_method(node->name, &(node->methods));
} else if (strcmp(type, keyword_enum) == 0) { } else if (strcmp(type, keyword_enum) == 0) {
@ -845,12 +849,19 @@ void handle_ap_object(void) {
} else if (strcmp(type, keyword_semaphore) == 0) { } else if (strcmp(type, keyword_semaphore) == 0) {
node->flags |= UD_FLAG_SEMAPHORE; node->flags |= UD_FLAG_SEMAPHORE;
} else if (strcmp(type, keyword_scheduler_semaphore) == 0) {
node->flags |= UD_FLAG_SCHEDULER_SEMAPHORE;
} else if (strcmp(type, keyword_method) == 0) { } else if (strcmp(type, keyword_method) == 0) {
handle_method(node->name, &(node->methods)); handle_method(node->name, &(node->methods));
} else { } else {
error(ERROR_SINGLETON, "AP_Objects only support aliases, methods or semaphore keyowrds (got %s)", type); error(ERROR_SINGLETON, "AP_Objects only support aliases, methods or semaphore keyowrds (got %s)", type);
} }
// check that we didn't just add 2 singleton flags
if ((node->flags & UD_FLAG_SEMAPHORE) && (node->flags & UD_FLAG_SCHEDULER_SEMAPHORE)) {
error(ERROR_SINGLETON, "Taking both a library semaphore and scheduler semaphore is prohibited");
}
// ensure no more tokens on the line // ensure no more tokens on the line
if (next_token()) { if (next_token()) {
error(ERROR_HEADER, "Singleton contained an unexpected extra token: %s", state.token); error(ERROR_HEADER, "Singleton contained an unexpected extra token: %s", state.token);
@ -1345,6 +1356,10 @@ void emit_userdata_method(const struct userdata *data, const struct method *meth
fprintf(source, " ud->get_semaphore().take_blocking();\n"); fprintf(source, " ud->get_semaphore().take_blocking();\n");
} }
if (data->flags & UD_FLAG_SCHEDULER_SEMAPHORE) {
fprintf(source, " AP::scheduler().get_semaphore().take_blocking();\n");
}
switch (method->return_type.type) { switch (method->return_type.type) {
case TYPE_BOOLEAN: case TYPE_BOOLEAN:
fprintf(source, " const bool data = ud->%s(", method->name); fprintf(source, " const bool data = ud->%s(", method->name);
@ -1433,6 +1448,10 @@ void emit_userdata_method(const struct userdata *data, const struct method *meth
fprintf(source, " ud->get_semaphore().give();\n"); fprintf(source, " ud->get_semaphore().give();\n");
} }
if (data->flags & UD_FLAG_SCHEDULER_SEMAPHORE) {
fprintf(source, " AP::scheduler().get_semaphore().give();\n");
}
int return_count = 1; // number of arguments to return int return_count = 1; // number of arguments to return
switch (method->return_type.type) { switch (method->return_type.type) {
case TYPE_BOOLEAN: case TYPE_BOOLEAN:

View File

@ -735,8 +735,10 @@ static int AP_Vehicle_get_time_flying_ms(lua_State *L) {
} }
binding_argcheck(L, 1); binding_argcheck(L, 1);
AP::scheduler().get_semaphore().take_blocking();
const uint32_t data = ud->get_time_flying_ms(); const uint32_t data = ud->get_time_flying_ms();
AP::scheduler().get_semaphore().give();
new_uint32_t(L); new_uint32_t(L);
*static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = data; *static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = data;
return 1; return 1;
@ -749,8 +751,10 @@ static int AP_Vehicle_get_likely_flying(lua_State *L) {
} }
binding_argcheck(L, 1); binding_argcheck(L, 1);
AP::scheduler().get_semaphore().take_blocking();
const bool data = ud->get_likely_flying(); const bool data = ud->get_likely_flying();
AP::scheduler().get_semaphore().give();
lua_pushboolean(L, data); lua_pushboolean(L, data);
return 1; return 1;
} }
@ -762,8 +766,10 @@ static int AP_Vehicle_get_mode(lua_State *L) {
} }
binding_argcheck(L, 1); binding_argcheck(L, 1);
AP::scheduler().get_semaphore().take_blocking();
const uint8_t data = ud->get_mode(); const uint8_t data = ud->get_mode();
AP::scheduler().get_semaphore().give();
lua_pushinteger(L, data); lua_pushinteger(L, data);
return 1; return 1;
} }
@ -778,10 +784,12 @@ static int AP_Vehicle_set_mode(lua_State *L) {
const lua_Integer raw_data_2 = luaL_checkinteger(L, 2); const lua_Integer raw_data_2 = luaL_checkinteger(L, 2);
luaL_argcheck(L, ((raw_data_2 >= MAX(0, 0)) && (raw_data_2 <= MIN(UINT8_MAX, UINT8_MAX))), 2, "argument out of range"); luaL_argcheck(L, ((raw_data_2 >= MAX(0, 0)) && (raw_data_2 <= MIN(UINT8_MAX, UINT8_MAX))), 2, "argument out of range");
const uint8_t data_2 = static_cast<uint8_t>(raw_data_2); const uint8_t data_2 = static_cast<uint8_t>(raw_data_2);
AP::scheduler().get_semaphore().take_blocking();
const bool data = ud->set_mode( const bool data = ud->set_mode(
data_2, data_2,
ModeReason::SCRIPTING); ModeReason::SCRIPTING);
AP::scheduler().get_semaphore().give();
lua_pushboolean(L, data); lua_pushboolean(L, data);
return 1; return 1;
} }