Browse Source

Make waiting for objects generic. Implement access granting/revoking.

coderain 5 years ago
parent
commit
7992a3f0b5

+ 5 - 4
kernel/include/object.h

@@ -23,10 +23,11 @@
 #include <common.h>
 #include <sdk/object.h>
 #include <sdk/list.h>
+#include <sdk/user.h>
 
 typedef struct
 {
-    list_entry_t list;
+    list_entry_t link;
     dword_t uid;
     access_flags_t access_mask;
 } access_control_entry_t;
@@ -39,12 +40,11 @@ typedef struct
     qword_t ref_count;
     dword_t open_count;
     object_type_t type;
-    access_control_policy_t acp;
+    uid_t owner;
+    qword_t acl_lock;
     list_entry_t acl;
 } object_t;
 
-typedef void (*object_cleanup_proc_t)(object_t *obj);
-
 static inline void init_object(object_t *object, const char *name, object_type_t type)
 {
     object->name = name ? strdup(name) : NULL;
@@ -60,5 +60,6 @@ dword_t open_object(object_t *obj, access_flags_t access_flags, handle_t *handle
 dword_t open_object_by_name(const char *name, object_type_t type, access_flags_t access_flags, handle_t *handle);
 void close_object_internal(object_t *obj);
 dword_t enum_objects_by_type(object_type_t type, object_t **object);
+void object_init(void);
 
 #endif

+ 1 - 0
kernel/include/process.h

@@ -76,6 +76,7 @@ extern process_t *kernel_process;
 process_t *get_current_process();
 void init_user_stack(uintptr_t *stack_pointer, process_params_t *parameters);
 void process_cleanup(object_t *proc);
+dword_t process_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);
 void destroy_process(process_t *process);
 process_t *switch_process(process_t *new_process);
 void process_init(void);

+ 1 - 1
kernel/include/semaphore.h

@@ -22,7 +22,7 @@
 
 #include <common.h>
 #include <object.h>
-#include <sdk/sync.h>
+#include <sdk/semaphore.h>
 
 #define init_mutex(m, i) init_semaphore((m), (i), 1)
 #define wait_mutex(m, t) wait_semaphore((m), 1, (t))

+ 1 - 0
kernel/include/thread.h

@@ -131,6 +131,7 @@ wait_result_t scheduler_wait(wait_condition_t *condition, dword_t timeout);
 dword_t create_system_thread(thread_procedure_t routine, dword_t flags, priority_t priority, dword_t stack_size, void *param, thread_t **new_thread);
 void thread_lazy_fpu(void);
 void thread_cleanup(object_t *thread);
+dword_t thread_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);
 void thread_init(void);
 
 #endif

+ 301 - 19
kernel/src/object.c

@@ -23,24 +23,36 @@
 #include <heap.h>
 #include <pipe.h>
 
+typedef void (*object_cleanup_proc_t)(object_t*);
+typedef dword_t (*object_pre_wait_proc_t)(object_t*, void*, wait_condition_t*);
+typedef void (*object_post_wait_proc_t)(object_t*, void*, wait_result_t);
+
 extern void file_cleanup(object_t*);
 extern void file_instance_cleanup(object_t*);
+extern dword_t semaphore_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);
+extern void semaphore_post_wait(object_t *obj, void *parameter, wait_result_t result);
 
 static lock_t obj_lock = 0;
 static DECLARE_LIST(anonymous_objects);
-static DECLARE_LIST_ARRAY(named_objects, 256);
-static DECLARE_LIST_ARRAY(objects_by_type, 9);
-static object_cleanup_proc_t cleanup_procedures[OBJECT_TYPE_MAX] =
+static list_entry_t named_objects[256];
+static list_entry_t objects_by_type[OBJECT_TYPE_MAX];
+
+static struct
+{
+    object_cleanup_proc_t cleanup;
+    object_pre_wait_proc_t pre_wait;
+    object_post_wait_proc_t post_wait;
+} type_info[OBJECT_TYPE_MAX] =
 {
-    file_cleanup,
-    file_instance_cleanup,
-    NULL,
-    (object_cleanup_proc_t)pipe_cleanup,
-    process_cleanup,
-    thread_cleanup,
-    memory_cleanup,
-    NULL,
-    NULL,
+    { .cleanup = file_cleanup,          .pre_wait = NULL,               .post_wait = NULL                },
+    { .cleanup = file_instance_cleanup, .pre_wait = NULL,               .post_wait = NULL                },
+    { .cleanup = NULL,                  .pre_wait = NULL,               .post_wait = NULL                },
+    { .cleanup = pipe_cleanup,          .pre_wait = pipe_pre_wait,      .post_wait = NULL                },
+    { .cleanup = process_cleanup,       .pre_wait = process_pre_wait,   .post_wait = NULL                },
+    { .cleanup = thread_cleanup,        .pre_wait = thread_pre_wait,    .post_wait = NULL                },
+    { .cleanup = memory_cleanup,        .pre_wait = NULL,               .post_wait = NULL                },
+    { .cleanup = NULL,                  .pre_wait = semaphore_pre_wait, .post_wait = semaphore_post_wait },
+    { .cleanup = NULL,                  .pre_wait = NULL,               .post_wait = NULL                },
 };
 
 static inline byte_t get_name_hash(const char *name)
@@ -84,7 +96,7 @@ cleanup:
     return i;
 }
 
-static bool_t access_check(object_t *obj, access_flags_t access_flags)
+static bool_t access_check(object_t *obj, access_flags_t access)
 {
     if (check_privileges(PRIVILEGE_ACCESS_ALL)) return TRUE;
 
@@ -93,11 +105,11 @@ static bool_t access_check(object_t *obj, access_flags_t access_flags)
 
     for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
     {
-        access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, list);
-        if (ace->uid == uid) return (access_flags == (access_flags & ace->access_mask));
+        access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
+        if ((ace->uid == ALL_USERS || ace->uid == uid) && access == (access & ace->access_mask)) return TRUE;
     }
 
-    return (obj->acp == ACCESS_DEFAULT_ALLOW) ? TRUE : FALSE;
+    return FALSE;
 }
 
 void reference(object_t *object)
@@ -122,7 +134,7 @@ void dereference(object_t *object)
 
     if (!ref_count)
     {
-        if (cleanup_procedures[object->type] != NULL) cleanup_procedures[object->type](object);
+        if (type_info[object->type].cleanup != NULL) type_info[object->type].cleanup(object);
         free(object);
     }
 }
@@ -137,7 +149,7 @@ bool_t reference_by_handle(handle_t handle, object_type_t type, object_t **objec
     acquire_resource_shared(&proc->handle_table_res);
 
     *object = proc->handle_table[handle].obj;
-    if (*object != NULL && (*object)->type == type)
+    if (*object != NULL && (type == OBJECT_ANY_TYPE || (*object)->type == type))
     {
         (*object)->ref_count++;
         result = TRUE;
@@ -173,6 +185,87 @@ bool_t reference_by_name(const char *name, object_type_t type, object_t **object
     return result;
 }
 
+dword_t grant_access(object_t *obj, dword_t uid, access_flags_t access)
+{
+    dword_t ret = ERR_SUCCESS;
+    reference(obj);
+    acquire_lock(&obj->acl_lock);
+
+    if (!access_check(obj, access))
+    {
+        ret = ERR_FORBIDDEN;
+        goto cleanup;
+    }
+
+    list_entry_t *ptr;
+    bool_t done = FALSE;
+
+    for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
+    {
+        access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
+        if (ace->uid == uid && (ace->access_mask & access) == access)
+        {
+            ace->access_mask |= access;
+            done = TRUE;
+            break;
+        }
+    }
+
+    if (!done)
+    {
+        access_control_entry_t *ace = malloc(sizeof(access_control_entry_t));
+        if (ace == NULL)
+        {
+            ret = ERR_NOMEMORY;
+            goto cleanup;
+        }
+
+        ace->uid = uid;
+        ace->access_mask = access;
+        list_append(&obj->acl, &ace->link);
+    }
+
+cleanup:
+    release_lock(&obj->acl_lock);
+    dereference(obj);
+    return ret;
+}
+
+dword_t revoke_access(object_t *obj, dword_t uid, access_flags_t access)
+{
+    dword_t ret = ERR_SUCCESS;
+    reference(obj);
+    acquire_lock(&obj->acl_lock);
+
+    if (get_current_uid() != obj->owner)
+    {
+        ret = ERR_FORBIDDEN;
+        goto cleanup;
+    }
+
+    list_entry_t *ptr;
+
+    for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
+    {
+        access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
+        if (ace->uid == uid && (ace->access_mask & access) == ace->access_mask)
+        {
+            if (!(ace->access_mask &= ~access))
+            {
+                ptr = ptr->prev;
+                list_remove(&ace->link);
+                free(ace);
+                ace = NULL;
+            }
+        }
+    }
+
+cleanup:
+    release_lock(&obj->acl_lock);
+    dereference(obj);
+    return ret;
+}
+
 dword_t create_object(object_t *obj)
 {
     if (obj->name != NULL)
@@ -188,6 +281,13 @@ dword_t create_object(object_t *obj)
 
     obj->ref_count = 1;
     obj->open_count = 0;
+    obj->owner = get_current_uid();
+    list_init(&obj->acl);
+
+    access_control_entry_t *ace = malloc(sizeof(access_control_entry_t));
+    ace->uid = get_current_uid();
+    ace->access_mask = FULL_ACCESS;
+    list_append(&obj->acl, &ace->link);
 
     acquire_lock(&obj_lock);
     if (obj->name) list_append(&named_objects[get_name_hash(obj->name)], &obj->by_name_list);
@@ -273,7 +373,7 @@ void close_object_internal(object_t *obj)
 
     if (!ref_count)
     {
-        if (cleanup_procedures[obj->type] != NULL) cleanup_procedures[obj->type](obj);
+        if (type_info[obj->type].cleanup != NULL) type_info[obj->type].cleanup(obj);
         free(obj);
     }
 }
@@ -480,3 +580,185 @@ dword_t enum_objects_by_type(object_type_t type, object_t **object)
     if (previous) dereference(previous);
     return ret;
 }
+
+static sysret_t wait_for_objects(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout, wait_condition_type_t condition_type)
+{
+    dword_t ret = ERR_SUCCESS;
+    object_t **objects = NULL;
+    wait_condition_t *condition = NULL;
+    const handle_t *safe_handles;
+    void * const *safe_parameters = NULL;
+    processor_mode_t previous_mode = get_previous_mode();
+    if (count == 0) return ERR_INVALID;
+
+    if (previous_mode == USER_MODE)
+    {
+        if (!check_usermode(handles, count * sizeof(handle_t))) return ERR_BADPTR;
+        if (parameters && !check_usermode(parameters, count * sizeof(void*))) return ERR_BADPTR;
+
+        safe_handles = calloc(count, sizeof(handle_t));
+        if (safe_handles == NULL) return ERR_NOMEMORY;
+
+        if (parameters)
+        {
+            safe_parameters = calloc(count, sizeof(void*));
+            if (safe_parameters == NULL)
+            {
+                free((void*)safe_handles);
+                return ERR_NOMEMORY;
+            }
+        }
+
+        EH_TRY
+        {
+            memcpy((handle_t*)safe_handles, handles, count * sizeof(handle_t));
+            if (safe_parameters) memcpy((void*)safe_parameters, parameters, count * sizeof(void*));
+        }
+        EH_CATCH
+        {
+            free((void*)safe_handles);
+            if (safe_parameters) free((void*)safe_parameters);
+            EH_ESCAPE(return ERR_BADPTR);
+        }
+        EH_DONE;
+    }
+    else
+    {
+        safe_handles = handles;
+        safe_parameters = parameters;
+    }
+
+    if (!(objects = calloc(count, sizeof(object_t*))))
+    {
+        ret = ERR_NOMEMORY;
+        goto cleanup;
+    }
+
+    size_t i;
+    for (i = 0; i < count; i++)
+    {
+        if (!reference_by_handle(safe_handles[i], OBJECT_ANY_TYPE, &objects[i]))
+        {
+            ret = ERR_INVALID;
+            goto cleanup;
+        }
+    }
+
+    if (!(condition = malloc(sizeof(wait_condition_t) + count * sizeof(wait_condition_t*))))
+    {
+        ret = ERR_NOMEMORY;
+        goto cleanup;
+    }
+
+    memset(condition, 0, sizeof(wait_condition_t) + (count + 1) * sizeof(wait_condition_t*));
+    condition->type = condition_type;
+
+    for (i = 0; i < count; i++)
+    {
+        if (!type_info[objects[i]->type].pre_wait)
+        {
+            ret = ERR_INVALID;
+            goto cleanup;
+        }
+
+        wait_condition_t *cond = malloc(sizeof(wait_condition_t));
+        if (!cond)
+        {
+            ret = ERR_NOMEMORY;
+            goto cleanup;
+        }
+
+        ret = type_info[objects[i]->type].pre_wait(objects[i], safe_parameters[i], cond);
+        if (ret != ERR_SUCCESS)
+        {
+            free(cond);
+            goto cleanup;
+        }
+
+        condition->conditions[i] = cond;
+    }
+
+    wait_result_t result = scheduler_wait(condition, timeout);
+    if (result == WAIT_CANCELED) ret = ERR_CANCELED;
+    else if (result == WAIT_TIMED_OUT) ret = ERR_TIMEOUT;
+
+    for (i = 0; i < count; i++)
+    {
+        if (type_info[objects[i]->type].post_wait)
+        {
+            type_info[objects[i]->type].post_wait(objects[i], safe_parameters ? safe_parameters[i] : NULL, result);
+        }
+    }
+
+cleanup:
+    if (condition)
+    {
+        for (i = 0; i < count; i++) if (condition->conditions[i]) free(condition->conditions[i]);
+        free(condition);
+    }
+
+    if (objects)
+    {
+        for (i = 0; i < count; i++) if (objects[i]) dereference(objects[i]);
+        free(objects);
+    }
+
+    if (previous_mode == USER_MODE)
+    {
+        free((void*)safe_handles);
+        if (safe_parameters) free((void*)safe_parameters);
+    }
+
+    return ret;
+}
+
+sysret_t syscall_wait_for_one(handle_t handle, void *parameter, timeout_t timeout)
+{
+    dword_t ret = ERR_SUCCESS;
+
+    object_t *object;
+    if (!reference_by_handle(handle, OBJECT_ANY_TYPE, &object)) return ERR_INVALID;
+
+    if (!type_info[object->type].pre_wait)
+    {
+        dereference(object);
+        return ERR_INVALID;
+    }
+
+    wait_condition_t condition;
+    ret = type_info[object->type].pre_wait(object, parameter, &condition);
+    if (ret != ERR_SUCCESS) return ret;
+
+    wait_result_t result = scheduler_wait(&condition, timeout);
+    dereference(object);
+
+    switch (result)
+    {
+    case WAIT_CONDITION_HIT:
+        return ERR_SUCCESS;
+    case WAIT_CANCELED:
+        return ERR_CANCELED;
+    case WAIT_TIMED_OUT:
+        return ERR_TIMEOUT;
+
+    default:
+        KERNEL_CRASH("Unexpected scheduler wait result");
+        return ERR_INVALID;
+    }
+}
+
+sysret_t syscall_wait_for_any(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout)
+{
+    return wait_for_objects(handles, parameters, count, timeout, WAIT_GROUP_ANY);
+}
+
+sysret_t syscall_wait_for_all(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout)
+{
+     return wait_for_objects(handles, parameters, count, timeout, WAIT_GROUP_ALL);
+}
+
+void object_init(void)
+{
+    list_init_array(named_objects, sizeof(named_objects) / sizeof(*named_objects));
+    list_init_array(objects_by_type, sizeof(objects_by_type) / sizeof(*objects_by_type));
+}

+ 10 - 0
kernel/src/pipe.c

@@ -186,6 +186,16 @@ void pipe_cleanup(object_t *obj)
     }
 }
 
+dword_t pipe_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition)
+{
+    pipe_t *pipe = (pipe_t*)obj;
+    dword_t min_bytes = parameter ? (dword_t)parameter : 1;
+    condition->type = WAIT_UNTIL_NOT_LESS;
+    condition->pointer = &pipe->bytes_ready;
+    condition->value = min_bytes;
+    return ERR_SUCCESS;
+}
+
 sysret_t syscall_create_pipeline(const char *name, dword_t flags, access_flags_t access, handle_t *handle)
 {
     dword_t ret;

+ 10 - 22
kernel/src/process.c

@@ -101,6 +101,16 @@ void process_cleanup(object_t *obj)
     release_lock(&pid_bitmap_lock);
 }
 
+dword_t process_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition)
+{
+    process_t *proc = (process_t*)obj;
+    UNUSED_PARAMETER(parameter);
+    condition->type = WAIT_UNTIL_NOT_EQUAL;
+    condition->pointer = &proc->terminated;
+    condition->value = 0;
+    return ERR_SUCCESS;
+}
+
 process_t *get_current_process()
 {
     thread_t *thread = get_current_thread();
@@ -696,28 +706,6 @@ cleanup:
     return ret;
 }
 
-sysret_t syscall_wait_process(handle_t handle, dword_t timeout)
-{
-    dword_t ret;
-    process_t *proc;
-
-    if (handle == INVALID_HANDLE)
-    {
-        proc = get_current_process();
-        reference(&proc->header);
-    }
-    else
-    {
-        if (!reference_by_handle(handle, OBJECT_PROCESS, (object_t**)&proc)) return ERR_INVALID;
-    }
-
-    wait_condition_t condition = { .type = WAIT_UNTIL_NOT_EQUAL, .pointer = &proc->terminated, .value = 0 };
-    ret = scheduler_wait(&condition, timeout);
-
-    dereference(&proc->header);
-    return ret;
-}
-
 process_t *switch_process(process_t *new_process)
 {
     thread_t *thread = get_current_thread();

+ 13 - 6
kernel/src/semaphore.c

@@ -135,15 +135,22 @@ dword_t release_semaphore(semaphore_t *semaphore, dword_t count)
     }
 }
 
-sysret_t syscall_wait_semaphore(handle_t semaphore, dword_t count, dword_t timeout)
+dword_t semaphore_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition)
 {
-    semaphore_t *obj;
+    semaphore_t *semaphore = (semaphore_t*)obj;
+    dword_t count = parameter ? (dword_t)parameter : 1;
+    if (count > semaphore->max_count) return ERR_INVALID;
 
-    if (!reference_by_handle(semaphore, OBJECT_SEMAPHORE, (object_t**)&obj)) return ERR_INVALID;
-    dword_t ret = wait_semaphore(obj, count, timeout);
-    dereference(&obj->header);
+    condition->type = WAIT_UNTIL_NOT_LESS;
+    condition->pointer = &semaphore->count;
+    condition->value = count;
+    return ERR_SUCCESS;
+}
 
-    return ret;
+void semaphore_post_wait(object_t *obj, void *parameter, wait_result_t result)
+{
+    semaphore_t *semaphore = (semaphore_t*)obj;
+    semaphore->count -= (dword_t)parameter;
 }
 
 sysret_t syscall_release_semaphore(handle_t semaphore, dword_t count)

+ 2 - 1
kernel/src/start.c

@@ -102,6 +102,7 @@ static void pre_initialization(void)
     syscalls_init();
     irq_init();
     exceptions_init();
+    object_init();
     enable_ints();
 }
 
@@ -352,7 +353,7 @@ void kernel_main(uintptr_t mboot_tags, size_t mboot_size)
     }
 
     handle_t manager_process = DO_TASK(start_system_manager);
-    syscall_wait_process(manager_process, NO_TIMEOUT);
+    syscall_wait_for_one(manager_process, NULL, NO_TIMEOUT);
 
     KERNEL_CRASH("The system manager has stopped working");
     ASSERT(FALSE);

+ 9 - 22
kernel/src/thread.c

@@ -137,6 +137,15 @@ void thread_cleanup(object_t *obj)
     if (CONTAINER_OF(obj, thread_t, header) == last_fpu_thread) last_fpu_thread = NULL;
 }
 
+dword_t thread_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition)
+{
+    thread_t *thread = (thread_t*)obj;
+    condition->type = WAIT_UNTIL_NOT_EQUAL;
+    condition->pointer = &thread->terminated;
+    condition->value = FALSE;
+    return ERR_SUCCESS;
+}
+
 dword_t create_thread_internal(process_t *proc, thread_state_t *initial_state, dword_t flags, priority_t priority, void *kernel_stack, thread_t **new_thread)
 {
     dword_t ret;
@@ -723,28 +732,6 @@ sysret_t syscall_set_thread(handle_t handle, thread_info_t info_type, const void
     return ret;
 }
 
-sysret_t syscall_wait_thread(handle_t handle, dword_t timeout)
-{
-    dword_t ret;
-    thread_t *thread;
-
-    if (handle == INVALID_HANDLE)
-    {
-        thread = get_current_thread();
-        reference(&thread->header);
-    }
-    else
-    {
-        if (!reference_by_handle(handle, OBJECT_THREAD, (object_t**)&thread)) return ERR_INVALID;
-    }
-
-    wait_condition_t condition = { .type = WAIT_UNTIL_NOT_EQUAL, .pointer = &thread->terminated, .value = FALSE };
-    ret = scheduler_wait(&condition, timeout);
-
-    dereference(&thread->header);
-    return ret;
-}
-
 sysret_t syscall_freeze_thread(handle_t handle)
 {
     dword_t ret = ERR_SUCCESS;

+ 6 - 258
sdk/list.h

@@ -22,266 +22,8 @@
 
 #include "defs.h"
 
-#define INITIALIZERS1(name) LIST_INITIALIZER(name[0])
-#define INITIALIZERS2(name) INITIALIZERS1(name), LIST_INITIALIZER(name[1])
-#define INITIALIZERS3(name) INITIALIZERS2(name), LIST_INITIALIZER(name[2])
-#define INITIALIZERS4(name) INITIALIZERS3(name), LIST_INITIALIZER(name[3])
-#define INITIALIZERS5(name) INITIALIZERS4(name), LIST_INITIALIZER(name[4])
-#define INITIALIZERS6(name) INITIALIZERS5(name), LIST_INITIALIZER(name[5])
-#define INITIALIZERS7(name) INITIALIZERS6(name), LIST_INITIALIZER(name[6])
-#define INITIALIZERS8(name) INITIALIZERS7(name), LIST_INITIALIZER(name[7])
-#define INITIALIZERS9(name) INITIALIZERS8(name), LIST_INITIALIZER(name[8])
-#define INITIALIZERS10(name) INITIALIZERS9(name), LIST_INITIALIZER(name[9])
-#define INITIALIZERS11(name) INITIALIZERS10(name), LIST_INITIALIZER(name[10])
-#define INITIALIZERS12(name) INITIALIZERS11(name), LIST_INITIALIZER(name[11])
-#define INITIALIZERS13(name) INITIALIZERS12(name), LIST_INITIALIZER(name[12])
-#define INITIALIZERS14(name) INITIALIZERS13(name), LIST_INITIALIZER(name[13])
-#define INITIALIZERS15(name) INITIALIZERS14(name), LIST_INITIALIZER(name[14])
-#define INITIALIZERS16(name) INITIALIZERS15(name), LIST_INITIALIZER(name[15])
-#define INITIALIZERS17(name) INITIALIZERS16(name), LIST_INITIALIZER(name[16])
-#define INITIALIZERS18(name) INITIALIZERS17(name), LIST_INITIALIZER(name[17])
-#define INITIALIZERS19(name) INITIALIZERS18(name), LIST_INITIALIZER(name[18])
-#define INITIALIZERS20(name) INITIALIZERS19(name), LIST_INITIALIZER(name[19])
-#define INITIALIZERS21(name) INITIALIZERS20(name), LIST_INITIALIZER(name[20])
-#define INITIALIZERS22(name) INITIALIZERS21(name), LIST_INITIALIZER(name[21])
-#define INITIALIZERS23(name) INITIALIZERS22(name), LIST_INITIALIZER(name[22])
-#define INITIALIZERS24(name) INITIALIZERS23(name), LIST_INITIALIZER(name[23])
-#define INITIALIZERS25(name) INITIALIZERS24(name), LIST_INITIALIZER(name[24])
-#define INITIALIZERS26(name) INITIALIZERS25(name), LIST_INITIALIZER(name[25])
-#define INITIALIZERS27(name) INITIALIZERS26(name), LIST_INITIALIZER(name[26])
-#define INITIALIZERS28(name) INITIALIZERS27(name), LIST_INITIALIZER(name[27])
-#define INITIALIZERS29(name) INITIALIZERS28(name), LIST_INITIALIZER(name[28])
-#define INITIALIZERS30(name) INITIALIZERS29(name), LIST_INITIALIZER(name[29])
-#define INITIALIZERS31(name) INITIALIZERS30(name), LIST_INITIALIZER(name[30])
-#define INITIALIZERS32(name) INITIALIZERS31(name), LIST_INITIALIZER(name[31])
-#define INITIALIZERS33(name) INITIALIZERS32(name), LIST_INITIALIZER(name[32])
-#define INITIALIZERS34(name) INITIALIZERS33(name), LIST_INITIALIZER(name[33])
-#define INITIALIZERS35(name) INITIALIZERS34(name), LIST_INITIALIZER(name[34])
-#define INITIALIZERS36(name) INITIALIZERS35(name), LIST_INITIALIZER(name[35])
-#define INITIALIZERS37(name) INITIALIZERS36(name), LIST_INITIALIZER(name[36])
-#define INITIALIZERS38(name) INITIALIZERS37(name), LIST_INITIALIZER(name[37])
-#define INITIALIZERS39(name) INITIALIZERS38(name), LIST_INITIALIZER(name[38])
-#define INITIALIZERS40(name) INITIALIZERS39(name), LIST_INITIALIZER(name[39])
-#define INITIALIZERS41(name) INITIALIZERS40(name), LIST_INITIALIZER(name[40])
-#define INITIALIZERS42(name) INITIALIZERS41(name), LIST_INITIALIZER(name[41])
-#define INITIALIZERS43(name) INITIALIZERS42(name), LIST_INITIALIZER(name[42])
-#define INITIALIZERS44(name) INITIALIZERS43(name), LIST_INITIALIZER(name[43])
-#define INITIALIZERS45(name) INITIALIZERS44(name), LIST_INITIALIZER(name[44])
-#define INITIALIZERS46(name) INITIALIZERS45(name), LIST_INITIALIZER(name[45])
-#define INITIALIZERS47(name) INITIALIZERS46(name), LIST_INITIALIZER(name[46])
-#define INITIALIZERS48(name) INITIALIZERS47(name), LIST_INITIALIZER(name[47])
-#define INITIALIZERS49(name) INITIALIZERS48(name), LIST_INITIALIZER(name[48])
-#define INITIALIZERS50(name) INITIALIZERS49(name), LIST_INITIALIZER(name[49])
-#define INITIALIZERS51(name) INITIALIZERS50(name), LIST_INITIALIZER(name[50])
-#define INITIALIZERS52(name) INITIALIZERS51(name), LIST_INITIALIZER(name[51])
-#define INITIALIZERS53(name) INITIALIZERS52(name), LIST_INITIALIZER(name[52])
-#define INITIALIZERS54(name) INITIALIZERS53(name), LIST_INITIALIZER(name[53])
-#define INITIALIZERS55(name) INITIALIZERS54(name), LIST_INITIALIZER(name[54])
-#define INITIALIZERS56(name) INITIALIZERS55(name), LIST_INITIALIZER(name[55])
-#define INITIALIZERS57(name) INITIALIZERS56(name), LIST_INITIALIZER(name[56])
-#define INITIALIZERS58(name) INITIALIZERS57(name), LIST_INITIALIZER(name[57])
-#define INITIALIZERS59(name) INITIALIZERS58(name), LIST_INITIALIZER(name[58])
-#define INITIALIZERS60(name) INITIALIZERS59(name), LIST_INITIALIZER(name[59])
-#define INITIALIZERS61(name) INITIALIZERS60(name), LIST_INITIALIZER(name[60])
-#define INITIALIZERS62(name) INITIALIZERS61(name), LIST_INITIALIZER(name[61])
-#define INITIALIZERS63(name) INITIALIZERS62(name), LIST_INITIALIZER(name[62])
-#define INITIALIZERS64(name) INITIALIZERS63(name), LIST_INITIALIZER(name[63])
-#define INITIALIZERS65(name) INITIALIZERS64(name), LIST_INITIALIZER(name[64])
-#define INITIALIZERS66(name) INITIALIZERS65(name), LIST_INITIALIZER(name[65])
-#define INITIALIZERS67(name) INITIALIZERS66(name), LIST_INITIALIZER(name[66])
-#define INITIALIZERS68(name) INITIALIZERS67(name), LIST_INITIALIZER(name[67])
-#define INITIALIZERS69(name) INITIALIZERS68(name), LIST_INITIALIZER(name[68])
-#define INITIALIZERS70(name) INITIALIZERS69(name), LIST_INITIALIZER(name[69])
-#define INITIALIZERS71(name) INITIALIZERS70(name), LIST_INITIALIZER(name[70])
-#define INITIALIZERS72(name) INITIALIZERS71(name), LIST_INITIALIZER(name[71])
-#define INITIALIZERS73(name) INITIALIZERS72(name), LIST_INITIALIZER(name[72])
-#define INITIALIZERS74(name) INITIALIZERS73(name), LIST_INITIALIZER(name[73])
-#define INITIALIZERS75(name) INITIALIZERS74(name), LIST_INITIALIZER(name[74])
-#define INITIALIZERS76(name) INITIALIZERS75(name), LIST_INITIALIZER(name[75])
-#define INITIALIZERS77(name) INITIALIZERS76(name), LIST_INITIALIZER(name[76])
-#define INITIALIZERS78(name) INITIALIZERS77(name), LIST_INITIALIZER(name[77])
-#define INITIALIZERS79(name) INITIALIZERS78(name), LIST_INITIALIZER(name[78])
-#define INITIALIZERS80(name) INITIALIZERS79(name), LIST_INITIALIZER(name[79])
-#define INITIALIZERS81(name) INITIALIZERS80(name), LIST_INITIALIZER(name[80])
-#define INITIALIZERS82(name) INITIALIZERS81(name), LIST_INITIALIZER(name[81])
-#define INITIALIZERS83(name) INITIALIZERS82(name), LIST_INITIALIZER(name[82])
-#define INITIALIZERS84(name) INITIALIZERS83(name), LIST_INITIALIZER(name[83])
-#define INITIALIZERS85(name) INITIALIZERS84(name), LIST_INITIALIZER(name[84])
-#define INITIALIZERS86(name) INITIALIZERS85(name), LIST_INITIALIZER(name[85])
-#define INITIALIZERS87(name) INITIALIZERS86(name), LIST_INITIALIZER(name[86])
-#define INITIALIZERS88(name) INITIALIZERS87(name), LIST_INITIALIZER(name[87])
-#define INITIALIZERS89(name) INITIALIZERS88(name), LIST_INITIALIZER(name[88])
-#define INITIALIZERS90(name) INITIALIZERS89(name), LIST_INITIALIZER(name[89])
-#define INITIALIZERS91(name) INITIALIZERS90(name), LIST_INITIALIZER(name[90])
-#define INITIALIZERS92(name) INITIALIZERS91(name), LIST_INITIALIZER(name[91])
-#define INITIALIZERS93(name) INITIALIZERS92(name), LIST_INITIALIZER(name[92])
-#define INITIALIZERS94(name) INITIALIZERS93(name), LIST_INITIALIZER(name[93])
-#define INITIALIZERS95(name) INITIALIZERS94(name), LIST_INITIALIZER(name[94])
-#define INITIALIZERS96(name) INITIALIZERS95(name), LIST_INITIALIZER(name[95])
-#define INITIALIZERS97(name) INITIALIZERS96(name), LIST_INITIALIZER(name[96])
-#define INITIALIZERS98(name) INITIALIZERS97(name), LIST_INITIALIZER(name[97])
-#define INITIALIZERS99(name) INITIALIZERS98(name), LIST_INITIALIZER(name[98])
-#define INITIALIZERS100(name) INITIALIZERS99(name), LIST_INITIALIZER(name[99])
-#define INITIALIZERS101(name) INITIALIZERS100(name), LIST_INITIALIZER(name[100])
-#define INITIALIZERS102(name) INITIALIZERS101(name), LIST_INITIALIZER(name[101])
-#define INITIALIZERS103(name) INITIALIZERS102(name), LIST_INITIALIZER(name[102])
-#define INITIALIZERS104(name) INITIALIZERS103(name), LIST_INITIALIZER(name[103])
-#define INITIALIZERS105(name) INITIALIZERS104(name), LIST_INITIALIZER(name[104])
-#define INITIALIZERS106(name) INITIALIZERS105(name), LIST_INITIALIZER(name[105])
-#define INITIALIZERS107(name) INITIALIZERS106(name), LIST_INITIALIZER(name[106])
-#define INITIALIZERS108(name) INITIALIZERS107(name), LIST_INITIALIZER(name[107])
-#define INITIALIZERS109(name) INITIALIZERS108(name), LIST_INITIALIZER(name[108])
-#define INITIALIZERS110(name) INITIALIZERS109(name), LIST_INITIALIZER(name[109])
-#define INITIALIZERS111(name) INITIALIZERS110(name), LIST_INITIALIZER(name[110])
-#define INITIALIZERS112(name) INITIALIZERS111(name), LIST_INITIALIZER(name[111])
-#define INITIALIZERS113(name) INITIALIZERS112(name), LIST_INITIALIZER(name[112])
-#define INITIALIZERS114(name) INITIALIZERS113(name), LIST_INITIALIZER(name[113])
-#define INITIALIZERS115(name) INITIALIZERS114(name), LIST_INITIALIZER(name[114])
-#define INITIALIZERS116(name) INITIALIZERS115(name), LIST_INITIALIZER(name[115])
-#define INITIALIZERS117(name) INITIALIZERS116(name), LIST_INITIALIZER(name[116])
-#define INITIALIZERS118(name) INITIALIZERS117(name), LIST_INITIALIZER(name[117])
-#define INITIALIZERS119(name) INITIALIZERS118(name), LIST_INITIALIZER(name[118])
-#define INITIALIZERS120(name) INITIALIZERS119(name), LIST_INITIALIZER(name[119])
-#define INITIALIZERS121(name) INITIALIZERS120(name), LIST_INITIALIZER(name[120])
-#define INITIALIZERS122(name) INITIALIZERS121(name), LIST_INITIALIZER(name[121])
-#define INITIALIZERS123(name) INITIALIZERS122(name), LIST_INITIALIZER(name[122])
-#define INITIALIZERS124(name) INITIALIZERS123(name), LIST_INITIALIZER(name[123])
-#define INITIALIZERS125(name) INITIALIZERS124(name), LIST_INITIALIZER(name[124])
-#define INITIALIZERS126(name) INITIALIZERS125(name), LIST_INITIALIZER(name[125])
-#define INITIALIZERS127(name) INITIALIZERS126(name), LIST_INITIALIZER(name[126])
-#define INITIALIZERS128(name) INITIALIZERS127(name), LIST_INITIALIZER(name[127])
-#define INITIALIZERS129(name) INITIALIZERS128(name), LIST_INITIALIZER(name[128])
-#define INITIALIZERS130(name) INITIALIZERS129(name), LIST_INITIALIZER(name[129])
-#define INITIALIZERS131(name) INITIALIZERS130(name), LIST_INITIALIZER(name[130])
-#define INITIALIZERS132(name) INITIALIZERS131(name), LIST_INITIALIZER(name[131])
-#define INITIALIZERS133(name) INITIALIZERS132(name), LIST_INITIALIZER(name[132])
-#define INITIALIZERS134(name) INITIALIZERS133(name), LIST_INITIALIZER(name[133])
-#define INITIALIZERS135(name) INITIALIZERS134(name), LIST_INITIALIZER(name[134])
-#define INITIALIZERS136(name) INITIALIZERS135(name), LIST_INITIALIZER(name[135])
-#define INITIALIZERS137(name) INITIALIZERS136(name), LIST_INITIALIZER(name[136])
-#define INITIALIZERS138(name) INITIALIZERS137(name), LIST_INITIALIZER(name[137])
-#define INITIALIZERS139(name) INITIALIZERS138(name), LIST_INITIALIZER(name[138])
-#define INITIALIZERS140(name) INITIALIZERS139(name), LIST_INITIALIZER(name[139])
-#define INITIALIZERS141(name) INITIALIZERS140(name), LIST_INITIALIZER(name[140])
-#define INITIALIZERS142(name) INITIALIZERS141(name), LIST_INITIALIZER(name[141])
-#define INITIALIZERS143(name) INITIALIZERS142(name), LIST_INITIALIZER(name[142])
-#define INITIALIZERS144(name) INITIALIZERS143(name), LIST_INITIALIZER(name[143])
-#define INITIALIZERS145(name) INITIALIZERS144(name), LIST_INITIALIZER(name[144])
-#define INITIALIZERS146(name) INITIALIZERS145(name), LIST_INITIALIZER(name[145])
-#define INITIALIZERS147(name) INITIALIZERS146(name), LIST_INITIALIZER(name[146])
-#define INITIALIZERS148(name) INITIALIZERS147(name), LIST_INITIALIZER(name[147])
-#define INITIALIZERS149(name) INITIALIZERS148(name), LIST_INITIALIZER(name[148])
-#define INITIALIZERS150(name) INITIALIZERS149(name), LIST_INITIALIZER(name[149])
-#define INITIALIZERS151(name) INITIALIZERS150(name), LIST_INITIALIZER(name[150])
-#define INITIALIZERS152(name) INITIALIZERS151(name), LIST_INITIALIZER(name[151])
-#define INITIALIZERS153(name) INITIALIZERS152(name), LIST_INITIALIZER(name[152])
-#define INITIALIZERS154(name) INITIALIZERS153(name), LIST_INITIALIZER(name[153])
-#define INITIALIZERS155(name) INITIALIZERS154(name), LIST_INITIALIZER(name[154])
-#define INITIALIZERS156(name) INITIALIZERS155(name), LIST_INITIALIZER(name[155])
-#define INITIALIZERS157(name) INITIALIZERS156(name), LIST_INITIALIZER(name[156])
-#define INITIALIZERS158(name) INITIALIZERS157(name), LIST_INITIALIZER(name[157])
-#define INITIALIZERS159(name) INITIALIZERS158(name), LIST_INITIALIZER(name[158])
-#define INITIALIZERS160(name) INITIALIZERS159(name), LIST_INITIALIZER(name[159])
-#define INITIALIZERS161(name) INITIALIZERS160(name), LIST_INITIALIZER(name[160])
-#define INITIALIZERS162(name) INITIALIZERS161(name), LIST_INITIALIZER(name[161])
-#define INITIALIZERS163(name) INITIALIZERS162(name), LIST_INITIALIZER(name[162])
-#define INITIALIZERS164(name) INITIALIZERS163(name), LIST_INITIALIZER(name[163])
-#define INITIALIZERS165(name) INITIALIZERS164(name), LIST_INITIALIZER(name[164])
-#define INITIALIZERS166(name) INITIALIZERS165(name), LIST_INITIALIZER(name[165])
-#define INITIALIZERS167(name) INITIALIZERS166(name), LIST_INITIALIZER(name[166])
-#define INITIALIZERS168(name) INITIALIZERS167(name), LIST_INITIALIZER(name[167])
-#define INITIALIZERS169(name) INITIALIZERS168(name), LIST_INITIALIZER(name[168])
-#define INITIALIZERS170(name) INITIALIZERS169(name), LIST_INITIALIZER(name[169])
-#define INITIALIZERS171(name) INITIALIZERS170(name), LIST_INITIALIZER(name[170])
-#define INITIALIZERS172(name) INITIALIZERS171(name), LIST_INITIALIZER(name[171])
-#define INITIALIZERS173(name) INITIALIZERS172(name), LIST_INITIALIZER(name[172])
-#define INITIALIZERS174(name) INITIALIZERS173(name), LIST_INITIALIZER(name[173])
-#define INITIALIZERS175(name) INITIALIZERS174(name), LIST_INITIALIZER(name[174])
-#define INITIALIZERS176(name) INITIALIZERS175(name), LIST_INITIALIZER(name[175])
-#define INITIALIZERS177(name) INITIALIZERS176(name), LIST_INITIALIZER(name[176])
-#define INITIALIZERS178(name) INITIALIZERS177(name), LIST_INITIALIZER(name[177])
-#define INITIALIZERS179(name) INITIALIZERS178(name), LIST_INITIALIZER(name[178])
-#define INITIALIZERS180(name) INITIALIZERS179(name), LIST_INITIALIZER(name[179])
-#define INITIALIZERS181(name) INITIALIZERS180(name), LIST_INITIALIZER(name[180])
-#define INITIALIZERS182(name) INITIALIZERS181(name), LIST_INITIALIZER(name[181])
-#define INITIALIZERS183(name) INITIALIZERS182(name), LIST_INITIALIZER(name[182])
-#define INITIALIZERS184(name) INITIALIZERS183(name), LIST_INITIALIZER(name[183])
-#define INITIALIZERS185(name) INITIALIZERS184(name), LIST_INITIALIZER(name[184])
-#define INITIALIZERS186(name) INITIALIZERS185(name), LIST_INITIALIZER(name[185])
-#define INITIALIZERS187(name) INITIALIZERS186(name), LIST_INITIALIZER(name[186])
-#define INITIALIZERS188(name) INITIALIZERS187(name), LIST_INITIALIZER(name[187])
-#define INITIALIZERS189(name) INITIALIZERS188(name), LIST_INITIALIZER(name[188])
-#define INITIALIZERS190(name) INITIALIZERS189(name), LIST_INITIALIZER(name[189])
-#define INITIALIZERS191(name) INITIALIZERS190(name), LIST_INITIALIZER(name[190])
-#define INITIALIZERS192(name) INITIALIZERS191(name), LIST_INITIALIZER(name[191])
-#define INITIALIZERS193(name) INITIALIZERS192(name), LIST_INITIALIZER(name[192])
-#define INITIALIZERS194(name) INITIALIZERS193(name), LIST_INITIALIZER(name[193])
-#define INITIALIZERS195(name) INITIALIZERS194(name), LIST_INITIALIZER(name[194])
-#define INITIALIZERS196(name) INITIALIZERS195(name), LIST_INITIALIZER(name[195])
-#define INITIALIZERS197(name) INITIALIZERS196(name), LIST_INITIALIZER(name[196])
-#define INITIALIZERS198(name) INITIALIZERS197(name), LIST_INITIALIZER(name[197])
-#define INITIALIZERS199(name) INITIALIZERS198(name), LIST_INITIALIZER(name[198])
-#define INITIALIZERS200(name) INITIALIZERS199(name), LIST_INITIALIZER(name[199])
-#define INITIALIZERS201(name) INITIALIZERS200(name), LIST_INITIALIZER(name[200])
-#define INITIALIZERS202(name) INITIALIZERS201(name), LIST_INITIALIZER(name[201])
-#define INITIALIZERS203(name) INITIALIZERS202(name), LIST_INITIALIZER(name[202])
-#define INITIALIZERS204(name) INITIALIZERS203(name), LIST_INITIALIZER(name[203])
-#define INITIALIZERS205(name) INITIALIZERS204(name), LIST_INITIALIZER(name[204])
-#define INITIALIZERS206(name) INITIALIZERS205(name), LIST_INITIALIZER(name[205])
-#define INITIALIZERS207(name) INITIALIZERS206(name), LIST_INITIALIZER(name[206])
-#define INITIALIZERS208(name) INITIALIZERS207(name), LIST_INITIALIZER(name[207])
-#define INITIALIZERS209(name) INITIALIZERS208(name), LIST_INITIALIZER(name[208])
-#define INITIALIZERS210(name) INITIALIZERS209(name), LIST_INITIALIZER(name[209])
-#define INITIALIZERS211(name) INITIALIZERS210(name), LIST_INITIALIZER(name[210])
-#define INITIALIZERS212(name) INITIALIZERS211(name), LIST_INITIALIZER(name[211])
-#define INITIALIZERS213(name) INITIALIZERS212(name), LIST_INITIALIZER(name[212])
-#define INITIALIZERS214(name) INITIALIZERS213(name), LIST_INITIALIZER(name[213])
-#define INITIALIZERS215(name) INITIALIZERS214(name), LIST_INITIALIZER(name[214])
-#define INITIALIZERS216(name) INITIALIZERS215(name), LIST_INITIALIZER(name[215])
-#define INITIALIZERS217(name) INITIALIZERS216(name), LIST_INITIALIZER(name[216])
-#define INITIALIZERS218(name) INITIALIZERS217(name), LIST_INITIALIZER(name[217])
-#define INITIALIZERS219(name) INITIALIZERS218(name), LIST_INITIALIZER(name[218])
-#define INITIALIZERS220(name) INITIALIZERS219(name), LIST_INITIALIZER(name[219])
-#define INITIALIZERS221(name) INITIALIZERS220(name), LIST_INITIALIZER(name[220])
-#define INITIALIZERS222(name) INITIALIZERS221(name), LIST_INITIALIZER(name[221])
-#define INITIALIZERS223(name) INITIALIZERS222(name), LIST_INITIALIZER(name[222])
-#define INITIALIZERS224(name) INITIALIZERS223(name), LIST_INITIALIZER(name[223])
-#define INITIALIZERS225(name) INITIALIZERS224(name), LIST_INITIALIZER(name[224])
-#define INITIALIZERS226(name) INITIALIZERS225(name), LIST_INITIALIZER(name[225])
-#define INITIALIZERS227(name) INITIALIZERS226(name), LIST_INITIALIZER(name[226])
-#define INITIALIZERS228(name) INITIALIZERS227(name), LIST_INITIALIZER(name[227])
-#define INITIALIZERS229(name) INITIALIZERS228(name), LIST_INITIALIZER(name[228])
-#define INITIALIZERS230(name) INITIALIZERS229(name), LIST_INITIALIZER(name[229])
-#define INITIALIZERS231(name) INITIALIZERS230(name), LIST_INITIALIZER(name[230])
-#define INITIALIZERS232(name) INITIALIZERS231(name), LIST_INITIALIZER(name[231])
-#define INITIALIZERS233(name) INITIALIZERS232(name), LIST_INITIALIZER(name[232])
-#define INITIALIZERS234(name) INITIALIZERS233(name), LIST_INITIALIZER(name[233])
-#define INITIALIZERS235(name) INITIALIZERS234(name), LIST_INITIALIZER(name[234])
-#define INITIALIZERS236(name) INITIALIZERS235(name), LIST_INITIALIZER(name[235])
-#define INITIALIZERS237(name) INITIALIZERS236(name), LIST_INITIALIZER(name[236])
-#define INITIALIZERS238(name) INITIALIZERS237(name), LIST_INITIALIZER(name[237])
-#define INITIALIZERS239(name) INITIALIZERS238(name), LIST_INITIALIZER(name[238])
-#define INITIALIZERS240(name) INITIALIZERS239(name), LIST_INITIALIZER(name[239])
-#define INITIALIZERS241(name) INITIALIZERS240(name), LIST_INITIALIZER(name[240])
-#define INITIALIZERS242(name) INITIALIZERS241(name), LIST_INITIALIZER(name[241])
-#define INITIALIZERS243(name) INITIALIZERS242(name), LIST_INITIALIZER(name[242])
-#define INITIALIZERS244(name) INITIALIZERS243(name), LIST_INITIALIZER(name[243])
-#define INITIALIZERS245(name) INITIALIZERS244(name), LIST_INITIALIZER(name[244])
-#define INITIALIZERS246(name) INITIALIZERS245(name), LIST_INITIALIZER(name[245])
-#define INITIALIZERS247(name) INITIALIZERS246(name), LIST_INITIALIZER(name[246])
-#define INITIALIZERS248(name) INITIALIZERS247(name), LIST_INITIALIZER(name[247])
-#define INITIALIZERS249(name) INITIALIZERS248(name), LIST_INITIALIZER(name[248])
-#define INITIALIZERS250(name) INITIALIZERS249(name), LIST_INITIALIZER(name[249])
-#define INITIALIZERS251(name) INITIALIZERS250(name), LIST_INITIALIZER(name[250])
-#define INITIALIZERS252(name) INITIALIZERS251(name), LIST_INITIALIZER(name[251])
-#define INITIALIZERS253(name) INITIALIZERS252(name), LIST_INITIALIZER(name[252])
-#define INITIALIZERS254(name) INITIALIZERS253(name), LIST_INITIALIZER(name[253])
-#define INITIALIZERS255(name) INITIALIZERS254(name), LIST_INITIALIZER(name[254])
-#define INITIALIZERS256(name) INITIALIZERS255(name), LIST_INITIALIZER(name[255])
-
 #define LIST_INITIALIZER(name) { &name, &name }
 #define DECLARE_LIST(name) list_entry_t name = LIST_INITIALIZER(name)
-#define DECLARE_LIST_ARRAY(name, size) list_entry_t name[size] = { INITIALIZERS##size(name) }
 
 #define list_put_after  list_prepend
 #define list_put_before list_append
@@ -318,4 +60,10 @@ static inline void list_init(list_entry_t *list)
     list->next = list->prev = list;
 }
 
+static inline void list_init_array(list_entry_t *list_array, size_t size)
+{
+    size_t i;
+    for (i = 0; i < size; i++) list_init(&list_array[i]);
+}
+
 #endif

+ 1 - 1
sdk/monolithium.h

@@ -28,7 +28,7 @@
 #include "pipe.h"
 #include "power.h"
 #include "process.h"
-#include "sync.h"
+#include "semaphore.h"
 #include "syscalls.h"
 #include "thread.h"
 #include "timer.h"

+ 7 - 7
sdk/object.h

@@ -22,7 +22,10 @@
 
 #include "defs.h"
 
-#define INVALID_HANDLE (handle_t)-1
+#define INVALID_HANDLE  (handle_t)-1
+#define NO_ACCESS       (access_flags_t)0
+#define FULL_ACCESS     (access_flags_t)-1
+#define OBJECT_ANY_TYPE OBJECT_TYPE_MAX
 
 typedef dword_t handle_t;
 typedef dword_t access_flags_t;
@@ -48,14 +51,11 @@ typedef enum
     HANDLE_INFO_TYPE,
 } handle_info_type_t;
 
-typedef enum
-{
-    ACCESS_DEFAULT_ALLOW = 0,
-    ACCESS_DEFAULT_DENY,
-} access_control_policy_t;
-
 sysret_t syscall_close_object(handle_t handle);
 sysret_t syscall_query_handle(handle_t handle, handle_info_type_t type, void *buffer, size_t size);
 sysret_t syscall_duplicate_handle(handle_t source_process, handle_t handle, handle_t dest_process, handle_t *duplicate);
+sysret_t syscall_wait_for_one(handle_t handle, void *parameter, timeout_t timeout);
+sysret_t syscall_wait_for_any(const handle_t *handles, void *const *parameters, size_t count, timeout_t timeout);
+sysret_t syscall_wait_for_all(const handle_t *handles, void *const *parameters, size_t count, timeout_t timeout);
 
 #endif

+ 0 - 1
sdk/process.h

@@ -54,6 +54,5 @@ sysret_t syscall_create_process(const char *path, dword_t flags, process_params_
 sysret_t syscall_terminate(handle_t handle, dword_t exit_code);
 sysret_t syscall_query_process(handle_t handle, process_info_t info_type, void *buffer, dword_t size);
 sysret_t syscall_enum_processes(dword_t *pid_array, dword_t *count);
-sysret_t syscall_wait_process(handle_t handle, dword_t timeout);
 
 #endif

+ 4 - 4
sdk/sync.h → sdk/semaphore.h

@@ -1,5 +1,5 @@
 /*
- * sync.h
+ * semaphore.h
  *
  * Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  *
@@ -17,8 +17,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MONOLITHIUM_SYNC_H__
-#define __MONOLITHIUM_SYNC_H__
+#ifndef __MONOLITHIUM_SEMAPHORE_H__
+#define __MONOLITHIUM_SEMAPHORE_H__
 
 #include "object.h"
 
@@ -26,12 +26,12 @@
 
 #define syscall_create_mutex(n, i, h) syscall_create_semaphore((n), (i), 1, (h))
 #define syscall_open_mutex(n, h) syscall_open_semaphore((n), (h))
+#define syscall_wait_semaphore(s, c, t) syscall_wait_for_one((s), (void*)(c), (t))
 #define syscall_wait_mutex(m, t) syscall_wait_semaphore((m), 1, (t))
 #define syscall_release_mutex(m) syscall_release_semaphore((m), 1)
 
 sysret_t syscall_create_semaphore(const char *name, dword_t init_count, dword_t max_count, handle_t *handle);
 sysret_t syscall_open_semaphore(const char *name, handle_t *handle);
-sysret_t syscall_wait_semaphore(handle_t semaphore, dword_t count, dword_t timeout);
 sysret_t syscall_release_semaphore(handle_t semaphore, dword_t count);
 
 #endif

+ 0 - 1
sdk/thread.h

@@ -97,6 +97,5 @@ sysret_t syscall_sleep(qword_t milliseconds);
 sysret_t syscall_yield_quantum(void);
 sysret_t syscall_query_thread(handle_t handle, thread_info_t info_type, void *buffer, size_t size);
 sysret_t syscall_set_thread(handle_t handle, thread_info_t info_type, const void *buffer, size_t size);
-sysret_t syscall_wait_thread(handle_t handle, dword_t timeout);
 
 #endif