lib: os: add sys_mutex data type

For systems without userspace enabled, these work the same
as a k_mutex.

For systems with userspace, the sys_mutex may exist in user
memory. It is still tracked as a kernel object, but has an
underlying k_mutex that is looked up in the kernel object
table.

Future enhancements will optimize sys_mutex to not require
syscalls for uncontended sys_mutexes, using atomic ops
instead.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
diff --git a/scripts/elf_helper.py b/scripts/elf_helper.py
index 209e345..005d9a2 100644
--- a/scripts/elf_helper.py
+++ b/scripts/elf_helper.py
@@ -37,6 +37,7 @@
 DW_OP_fbreg = 0x91
 STACK_TYPE = "_k_thread_stack_element"
 thread_counter = 0
+sys_mutex_counter = 0
 
 # Global type environment. Populated by pass 1.
 type_env = {}
@@ -54,6 +55,7 @@
 class KobjectInstance:
     def __init__(self, type_obj, addr):
         global thread_counter
+        global sys_mutex_counter
 
         self.addr = addr
         self.type_obj = type_obj
@@ -67,6 +69,9 @@
             # permissions to other kernel objects
             self.data = thread_counter
             thread_counter = thread_counter + 1
+        elif self.type_obj.name == "sys_mutex":
+            self.data = "(u32_t)(&kernel_mutexes[%d])" % sys_mutex_counter
+            sys_mutex_counter += 1
         else:
             self.data = 0
 
@@ -558,3 +563,6 @@
 
     def get_thread_counter(self):
         return thread_counter
+
+    def get_sys_mutex_counter(self):
+        return sys_mutex_counter
diff --git a/scripts/gen_kobject_list.py b/scripts/gen_kobject_list.py
index 89358e4..e641254 100755
--- a/scripts/gen_kobject_list.py
+++ b/scripts/gen_kobject_list.py
@@ -83,6 +83,7 @@
     ("k_timer", (None, False)),
     ("_k_thread_stack_element", (None, False)),
     ("device", (None, False)),
+    ("sys_mutex", (None, True))
 ])
 
 
@@ -122,10 +123,8 @@
 #include <string.h>
 %}
 struct _k_object;
-%%
 """
 
-
 # Different versions of gperf have different prototypes for the lookup
 # function, best to implement the wrapper here. The pointer value itself is
 # turned into a string, we told gperf to expect binary strings that are not
@@ -159,7 +158,16 @@
 
 def write_gperf_table(fp, eh, objs, static_begin, static_end):
     fp.write(header)
+    num_mutexes = eh.get_sys_mutex_counter()
+    if (num_mutexes != 0):
+        fp.write("static struct k_mutex kernel_mutexes[%d] = {\n" % num_mutexes)
+        for i in range(num_mutexes):
+            fp.write("_K_MUTEX_INITIALIZER(kernel_mutexes[%d])" % i)
+            if (i != num_mutexes - 1):
+                fp.write(", ")
+        fp.write("};\n")
 
+    fp.write("%%\n")
     # Setup variables for mapping thread indexes
     syms = eh.get_symbols()
     thread_max_bytes = syms["CONFIG_MAX_THREAD_BYTES"]