Browse Source

Replace Linux List code with a new implementation (#71)

* Remove the Linux linked list implementation, replace with a new implementation that adds some type-checking that list pointers (heads) and entries/nodes match.

* Fix the debug build by consolidating assertions into one header
Don Porter 6 years ago
parent
commit
2e9438f71c
51 changed files with 1575 additions and 1485 deletions
  1. 10 9
      LibOS/shim/include/shim_fs.h
  2. 21 13
      LibOS/shim/include/shim_handle.h
  3. 1 11
      LibOS/shim/include/shim_internal.h
  4. 10 6
      LibOS/shim/include/shim_ipc.h
  5. 17 14
      LibOS/shim/include/shim_sysv.h
  6. 12 9
      LibOS/shim/include/shim_thread.h
  7. 1 1
      LibOS/shim/include/shim_utils.h
  8. 3 2
      LibOS/shim/include/shim_vma.h
  9. 2 2
      LibOS/shim/src/bookkeep/shim_handle.c
  10. 59 36
      LibOS/shim/src/bookkeep/shim_thread.c
  11. 48 34
      LibOS/shim/src/bookkeep/shim_vma.c
  12. 58 44
      LibOS/shim/src/fs/shim_dcache.c
  13. 10 8
      LibOS/shim/src/fs/shim_fs.c
  14. 1 1
      LibOS/shim/src/fs/shim_namei.c
  15. 19 17
      LibOS/shim/src/ipc/shim_ipc.c
  16. 42 40
      LibOS/shim/src/ipc/shim_ipc_helper.c
  17. 71 49
      LibOS/shim/src/ipc/shim_ipc_nsimpl.h
  18. 24 19
      LibOS/shim/src/ipc/shim_ipc_pid.c
  19. 44 20
      LibOS/shim/src/shim_async.c
  20. 9 8
      LibOS/shim/src/shim_checkpoint.c
  21. 32 49
      LibOS/shim/src/sys/shim_epoll.c
  22. 17 12
      LibOS/shim/src/sys/shim_exec.c
  23. 6 5
      LibOS/shim/src/sys/shim_exit.c
  24. 52 69
      LibOS/shim/src/sys/shim_futex.c
  25. 26 17
      LibOS/shim/src/sys/shim_migrate.c
  26. 31 27
      LibOS/shim/src/sys/shim_msgget.c
  27. 1 1
      LibOS/shim/src/sys/shim_poll.c
  28. 63 50
      LibOS/shim/src/sys/shim_semget.c
  29. 14 11
      LibOS/shim/src/sys/shim_wait.c
  30. 1 1
      LibOS/shim/test/regression/90_large-mmap.py
  31. 5 2
      Pal/lib/api.h
  32. 1 3
      Pal/lib/crypto/adapters/mbedtls_adapter.c
  33. 1 3
      Pal/lib/crypto/adapters/wolfssl_adapter.c
  34. 41 39
      Pal/lib/graphene/config.c
  35. 0 717
      Pal/lib/linux_list.h
  36. 324 0
      Pal/lib/list-test.c
  37. 339 0
      Pal/lib/list.h
  38. 34 30
      Pal/lib/memmgr.h
  39. 0 1
      Pal/lib/pal_crypto.h
  40. 28 19
      Pal/lib/slabmgr.h
  41. 2 1
      Pal/src/db_exception.c
  42. 1 1
      Pal/src/host/FreeBSD/db_exception.c
  43. 9 7
      Pal/src/host/Linux-SGX/db_process.c
  44. 11 10
      Pal/src/host/Linux-SGX/db_threading.c
  45. 16 14
      Pal/src/host/Linux-SGX/enclave_framework.c
  46. 45 25
      Pal/src/host/Linux-SGX/enclave_pages.c
  47. 1 1
      Pal/src/host/Linux-SGX/enclave_untrusted.c
  48. 11 7
      Pal/src/host/Linux-SGX/pal_host.h
  49. 0 1
      Pal/src/host/Linux-SGX/sgx_graphene.c
  50. 1 18
      Pal/src/pal_debug.h
  51. 0 1
      Pal/src/slab.c

+ 10 - 9
LibOS/shim/include/shim_fs.h

@@ -32,7 +32,7 @@
 #include <shim_utils.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 struct shim_handle;
 
@@ -121,6 +121,8 @@ struct shim_fs_ops {
 #define DCACHE_HASH_SIZE    1024
 #define DCACHE_HASH(hash) ((hash) & (DCACHE_HASH_SIZE - 1))
 
+DEFINE_LIST(shim_dentry);
+DEFINE_LISTP(shim_dentry);
 struct shim_dentry {
     int state;  /* flags for managing state */
 
@@ -130,16 +132,16 @@ struct shim_dentry {
     struct shim_qstr name;          /* caching the file's name. */
 
 
-    struct hlist_node hlist;        /* to resolve collisions in
+    LIST_TYPE(shim_dentry) hlist;    /* to resolve collisions in
                                        the hash table */
-    struct list_head list;          /* put dentry to different list
+    LIST_TYPE(shim_dentry) list;     /* put dentry to different list
                                        according to its availability,
                                        persistent or freeable */
 
     struct shim_dentry * parent;
     int nchildren;
-    struct list_head children;
-    struct list_head siblings;
+    LISTP_TYPE(shim_dentry) children; /* These children and siblings link */
+    LIST_TYPE(shim_dentry) siblings;
 
     struct shim_mount * mounted;
     void * data;
@@ -201,6 +203,7 @@ struct shim_d_ops {
 
 #define MAX_PATH        4096
 
+DEFINE_LIST(shim_mount);
 struct shim_mount {
     char type[8];
 
@@ -220,8 +223,8 @@ struct shim_mount {
     size_t cpsize;
 
     REFTYPE ref_count;
-    struct hlist_node hlist;
-    struct list_head list;
+    LIST_TYPE(shim_mount) hlist;
+    LIST_TYPE(shim_mount) list;
 };
 
 extern struct shim_dentry * dentry_root;
@@ -403,8 +406,6 @@ void __unset_parent_dentry (struct shim_dentry * child,
 
 void __add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr);
 void add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr);
-void __del_dcache (struct shim_dentry * dent);
-void del_dcache (struct shim_dentry * dent);
 
 struct shim_dentry *
 __lookup_dcache (struct shim_dentry * start, const char * name, int namelen,

+ 21 - 13
LibOS/shim/include/shim_handle.h

@@ -31,7 +31,7 @@
 #include <shim_sysv.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <linux/shm.h>
 #include <linux/in.h>
@@ -233,6 +233,7 @@ struct msg_client;
 
 #define MAX_SYSV_CLIENTS        32
 
+DEFINE_LIST(shim_msg_handle);
 struct shim_msg_handle {
     unsigned long       msqkey;         /* msg queue key from user */
     IDTYPE              msqid;          /* msg queue identifier */
@@ -252,13 +253,14 @@ struct shim_msg_handle {
     int                 maxtypes;
     struct msg_type *   types;
     struct sysv_score   scores[MAX_SYSV_CLIENTS];
-    struct list_head    list;
-    struct hlist_node   key_hlist;
-    struct hlist_node   qid_hlist;
+    LIST_TYPE(shim_msg_handle) list;
+    LIST_TYPE(shim_msg_handle) key_hlist;
+    LIST_TYPE(shim_msg_handle) qid_hlist;
 };
 
 struct sem_objs;
 
+DEFINE_LIST(shim_sem_handle);
 struct shim_sem_handle {
     unsigned long       semkey;
     IDTYPE              semid;
@@ -272,17 +274,19 @@ struct shim_sem_handle {
     struct sem_obj *    sems;
     int                 nreqs;
     struct sysv_score   scores[MAX_SYSV_CLIENTS];
-    struct list_head    migrated;
-    struct list_head    list;
-    struct hlist_node   key_hlist;
-    struct hlist_node   sid_hlist;
+    LISTP_TYPE(sem_ops) migrated;
+    LIST_TYPE(shim_sem_handle) list;
+    LIST_TYPE(shim_sem_handle) key_hlist;
+    LIST_TYPE(shim_sem_handle) sid_hlist;
 };
-
+DEFINE_LIST(futex_waiter);
+DEFINE_LISTP(futex_waiter);
+DEFINE_LIST(shim_futex_handle);
 struct shim_futex_handle {
     unsigned int *      uaddr;
-    struct list_head    waiters;
+    LISTP_TYPE(futex_waiter) waiters;
     struct shim_vma *   vma;
-    struct list_head    list;
+    LIST_TYPE(shim_futex_handle) list;
 };
 
 struct shim_str_data {
@@ -301,10 +305,12 @@ struct shim_str_handle {
     char * ptr;
 };
 
+DEFINE_LIST(shim_epoll_fd);
+DEFINE_LISTP(shim_epoll_fd);
 struct shim_epoll_handle {
     int                 maxfds;
     int                 nfds;
-    struct list_head    fds;
+    LISTP_TYPE(shim_epoll_fd) fds;
     FDTYPE *            pal_fds;
     PAL_HANDLE *        pal_handles;
     int                 npals;
@@ -317,6 +323,8 @@ struct shim_mount;
 struct shim_qstr;
 struct shim_dentry;
 
+/* The epolls list links to the back field of the shim_epoll_fd structure 
+ */
 struct shim_handle {
     enum shim_handle_type   type;
 
@@ -326,7 +334,7 @@ struct shim_handle {
     struct shim_mount *     fs;
     struct shim_qstr        path;
     struct shim_dentry *    dentry;
-    struct list_head        epolls;
+    LISTP_TYPE(shim_epoll_fd) epolls;
 
     struct shim_qstr        uri;    /* URI representing this handle, it is not
                                      * necessary to be set. */

+ 1 - 11
LibOS/shim/include/shim_internal.h

@@ -152,17 +152,7 @@ static inline void do_pause (void);
     } while (0)
 
 #if USE_ASSERT == 1
-# define assert(test)                                                       \
-    ({                                                                      \
-        long _val = (long) (test);                                          \
-        (!(_val))                                                           \
-        ? ({                                                                \
-            __sys_printf("assert failed " __FILE__ ":%d " #test " (value:%x)\n", \
-                    __LINE__, _val);                                        \
-            pause();                                                        \
-            shim_terminate(); })                                            \
-        : (void) 0;                                                         \
-    })
+#include <assert.h>
 #else
 # define assert(test) do {} while (0)
 #endif

+ 10 - 6
LibOS/shim/include/shim_ipc.h

@@ -33,14 +33,15 @@
 #include <shim_sysv.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
+DEFINE_LIST(shim_ipc_info);
 struct shim_ipc_info {
     IDTYPE                  vmid;
     struct shim_ipc_port *  port;
     PAL_HANDLE              pal_handle;
     struct shim_qstr        uri;
-    struct hlist_node       hlist;
+    LIST_TYPE(shim_ipc_info) hlist;
     REFTYPE                 ref_count;
 };
 
@@ -73,9 +74,10 @@ struct shim_ipc_msg {
 struct shim_ipc_port;
 struct shim_thread;
 
+DEFINE_LIST(shim_ipc_msg_obj);
 struct shim_ipc_msg_obj {
     struct shim_thread *    thread;
-    struct list_head        list;
+    LIST_TYPE(shim_ipc_msg_obj) list;
     int                     retval;
     void *                  private;
     struct shim_ipc_msg     msg;
@@ -86,13 +88,15 @@ typedef void (*port_fini) (struct shim_ipc_port *, IDTYPE vmid,
 
 #define MAX_IPC_PORT_FINI_CB        3
 
+DEFINE_LIST(shim_ipc_port);
+DEFINE_LISTP(shim_ipc_msg_obj);
 struct shim_ipc_port {
     PAL_HANDLE          pal_handle;
 
     REFTYPE             ref_count;
-    struct hlist_node   hlist;
-    struct list_head    list;
-    struct list_head    msgs;
+    LIST_TYPE(shim_ipc_port) hlist;
+    LIST_TYPE(shim_ipc_port) list;
+    LISTP_TYPE(shim_ipc_msg_obj) msgs;
     LOCKTYPE            msgs_lock;
 
     port_fini           fini[MAX_IPC_PORT_FINI_CB];

+ 17 - 14
LibOS/shim/include/shim_sysv.h

@@ -69,7 +69,7 @@ int __balance_sysv_score (struct sysv_balance_policy * policy,
 
 #define MSG_NOERROR 010000
 
-#include <linux_list.h>
+#include <list.h>
 
 struct __kernel_msgbuf {
     long mtype;     /* type of message */
@@ -160,20 +160,9 @@ int store_all_msg_persist (void);
 
 #define HOST_SEM_NUM        65535
 
-struct sem_obj {
-    unsigned short      num;
-    unsigned short      val;
-    unsigned short      zcnt;
-    unsigned short      ncnt;
-    IDTYPE              pid;
-    PAL_NUM             host_sem_id;
-    PAL_HANDLE          host_sem;
-    struct list_head    ops;
-    struct list_head    next_ops;
-};
-
+DEFINE_LIST(sem_ops);
 struct sem_ops {
-    struct list_head   progress;
+    LIST_TYPE(sem_ops)      progress;
     struct sem_stat {
         bool                completed;
         bool                failed;
@@ -185,6 +174,20 @@ struct sem_ops {
     struct sembuf ops[];
 };
 
+DEFINE_LISTP(sem_ops);
+struct sem_obj {
+    unsigned short      num;
+    unsigned short      val;
+    unsigned short      zcnt;
+    unsigned short      ncnt;
+    IDTYPE              pid;
+    PAL_NUM             host_sem_id;
+    PAL_HANDLE          host_sem;
+    LISTP_TYPE(sem_ops) ops;
+    LISTP_TYPE(sem_ops) next_ops;
+};
+
+
 #define SEM_POSITIVE_SCORE(num)  ((num) < 5 ? 5 - (num) : 1)
 #define SEM_ZERO_SCORE           20
 #define SEM_NEGATIVE_SCORE(num)  (20 * (num))

+ 12 - 9
LibOS/shim/include/shim_thread.h

@@ -13,7 +13,7 @@
 #include <shim_vma.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 struct shim_handle;
 struct shim_fd_map;
@@ -21,6 +21,8 @@ struct shim_dentry;
 struct shim_signal_handle;
 struct shim_signal_log;
 
+DEFINE_LIST(shim_thread);
+DEFINE_LISTP(shim_thread);
 struct shim_thread {
     /* thread identifiers */
     IDTYPE vmid;
@@ -40,12 +42,12 @@ struct shim_thread {
     struct shim_thread * leader;
     /* dummy thread */
     struct shim_thread * dummy;
-    /* child handles */
-    struct list_head children;
-    /* nodes in child handles */
-    struct list_head siblings;
-    /* nodes in global handles */
-    struct list_head list;
+    /* child handles; protected by thread->lock */
+    LISTP_TYPE(shim_thread) children;
+    /* nodes in child handles; protected by the parent's lock */
+    LIST_TYPE(shim_thread) siblings;
+    /* nodes in global handles; protected by thread_list_lock */
+    LIST_TYPE(shim_thread) list;
 
     struct shim_handle_map * handle_map;
 
@@ -72,7 +74,7 @@ struct shim_thread {
     bool is_alive;
 
     PAL_HANDLE child_exit_event;
-    struct list_head exited_children;
+    LISTP_TYPE(shim_thread) exited_children;
 
     /* file system */
     struct shim_dentry * root, * cwd;
@@ -97,6 +99,7 @@ struct shim_thread {
 #endif
 };
 
+DEFINE_LIST(shim_simple_thread);
 struct shim_simple_thread {
     /* VMID and PIDs */
     IDTYPE vmid;
@@ -109,7 +112,7 @@ struct shim_simple_thread {
     bool is_alive;
 
     /* nodes in global handles */
-    struct list_head list;
+    LIST_TYPE(shim_simple_thread) list;
 
     REFTYPE ref_count;
     LOCKTYPE lock;

+ 1 - 1
LibOS/shim/include/shim_utils.h

@@ -27,7 +27,7 @@
 #include <shim_handle.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 #include <api.h>
 
 struct shim_handle;

+ 3 - 2
LibOS/shim/include/shim_vma.h

@@ -31,7 +31,7 @@
 #include <shim_handle.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <asm/mman.h>
 
@@ -39,6 +39,7 @@ struct shim_handle;
 
 #define VMA_COMMENT_LEN     16
 
+DEFINE_LIST(shim_vma);
 struct shim_vma {
     REFTYPE                 ref_count;
     void *                  addr;
@@ -47,7 +48,7 @@ struct shim_vma {
     int                     flags;
     uint64_t                offset;
     struct shim_handle *    file;
-    struct list_head        list;
+    LIST_TYPE(shim_vma)     list;
     char                    comment[VMA_COMMENT_LEN];
 };
 

+ 2 - 2
LibOS/shim/src/bookkeep/shim_handle.c

@@ -285,7 +285,7 @@ struct shim_handle * get_new_handle (void)
     REF_SET(new_handle->ref_count, 1);
     create_lock(new_handle->lock);
     new_handle->owner = cur_process.vmid;
-    INIT_LIST_HEAD(&new_handle->epolls);
+    INIT_LISTP(&new_handle->epolls);
     return new_handle;
 }
 
@@ -812,7 +812,7 @@ BEGIN_CP_FUNC(handle)
         if (hdl->type == TYPE_EPOLL)
             DO_CP(epoll_fd, &hdl->info.epoll.fds, &new_hdl->info.epoll.fds);
 
-        INIT_LIST_HEAD(&new_hdl->epolls);
+        INIT_LISTP(&new_hdl->epolls);
 
         unlock(hdl->lock);
         ADD_CP_FUNC_ENTRY(off);

+ 59 - 36
LibOS/shim/src/bookkeep/shim_thread.c

@@ -31,12 +31,13 @@
 #include <shim_checkpoint.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 static IDTYPE tid_alloc_idx __attribute_migratable = 0;
 
-static LIST_HEAD(thread_list);
-static LIST_HEAD(simple_thread_list);
+static LISTP_TYPE(shim_thread) thread_list = LISTP_INIT;
+DEFINE_LISTP(shim_simple_thread);
+static LISTP_TYPE(shim_simple_thread) simple_thread_list = LISTP_INIT;
 LOCKTYPE thread_list_lock;
 
 static IDTYPE internal_tid_alloc_idx = INTERNAL_TID_BASE;
@@ -63,15 +64,28 @@ int init_thread (void)
     return 0;
 }
 
+void dump_threads (void)
+{
+    struct shim_thread * tmp;
+
+    lock(thread_list_lock);
+    listp_for_each_entry(tmp, &thread_list, list) {
+        debug("thread %d, vmid = %d, pgid = %d, ppid = %d, tgid = %d, in_vm = %d\n",
+                tmp->tid, tmp->vmid, tmp->pgid, tmp->ppid, tmp->tgid, tmp->in_vm);
+    }
+    unlock(thread_list_lock);
+}
+
 struct shim_thread * __lookup_thread (IDTYPE tid)
 {
     struct shim_thread * tmp;
 
-    list_for_each_entry(tmp, &thread_list, list)
+    listp_for_each_entry(tmp, &thread_list, list) {
         if (tmp->tid == tid) {
             get_thread(tmp);
             return tmp;
         }
+    }
 
     return NULL;
 }
@@ -144,10 +158,10 @@ struct shim_thread * alloc_new_thread (void)
 
     memset(thread, 0, sizeof(struct shim_thread));
     REF_SET(thread->ref_count, 1);
-    INIT_LIST_HEAD(&thread->children);
-    INIT_LIST_HEAD(&thread->siblings);
-    INIT_LIST_HEAD(&thread->exited_children);
-    INIT_LIST_HEAD(&thread->list);
+    INIT_LISTP(&thread->children);
+    INIT_LIST_HEAD(thread, siblings);
+    INIT_LISTP(&thread->exited_children);
+    INIT_LIST_HEAD(thread, list);
     return thread;
 }
 
@@ -248,11 +262,12 @@ struct shim_simple_thread * __lookup_simple_thread (IDTYPE tid)
 {
     struct shim_simple_thread * tmp;
 
-    list_for_each_entry(tmp, &simple_thread_list, list)
+    listp_for_each_entry(tmp, &simple_thread_list, list) {
         if (tmp->tid == tid) {
             get_simple_thread(tmp);
             return tmp;
         }
+    }
 
     return NULL;
 }
@@ -275,7 +290,7 @@ struct shim_simple_thread * get_new_simple_thread (void)
 
     memset(thread, 0, sizeof(struct shim_simple_thread));
 
-    INIT_LIST_HEAD(&thread->list);
+    INIT_LIST_HEAD(thread, list);
 
     create_lock(thread->lock);
     thread->exit_event = DkNotificationEventCreate(PAL_FALSE);
@@ -328,7 +343,8 @@ void put_simple_thread (struct shim_simple_thread * thread)
     int ref_count = REF_DEC(thread->ref_count);
 
     if (!ref_count) {
-        list_del(&thread->list);
+        /* Simple threads always live on the simple thread list */
+        listp_del(thread, &simple_thread_list, list);
         free(thread);
     }
 }
@@ -347,7 +363,7 @@ void set_as_child (struct shim_thread * parent,
     child->parent = parent;
 
     lock(parent->lock);
-    list_add_tail(&child->siblings, &parent->children);
+    listp_add_tail(child, &parent->children, siblings);
     unlock(parent->lock);
 
     unlock(child->lock);
@@ -355,14 +371,14 @@ void set_as_child (struct shim_thread * parent,
 
 void add_thread (struct shim_thread * thread)
 {
-    if (IS_INTERNAL(thread) || !list_empty(&thread->list))
+    if (IS_INTERNAL(thread) || !list_empty(thread, list))
         return;
 
     struct shim_thread * tmp, * prev = NULL;
     lock(thread_list_lock);
 
     /* keep it sorted */
-    list_for_each_entry_reverse(tmp, &thread_list, list) {
+    listp_for_each_entry_reverse(tmp, &thread_list, list) {
         if (tmp->tid == thread->tid) {
             unlock(thread_list_lock);
             return;
@@ -374,31 +390,37 @@ void add_thread (struct shim_thread * thread)
     }
 
     get_thread(thread);
-    list_add(&thread->list, prev ? &prev->list : &thread_list);
+    listp_add_after(thread, prev, &thread_list, list);
     unlock(thread_list_lock);
 }
 
 void del_thread (struct shim_thread * thread)
 {
-    if (IS_INTERNAL(thread) || list_empty(&thread->list))
+    debug("del_thread(%p, %d, %d)\n", thread, thread ? thread->tid : -1,
+            thread->ref_count);
+
+    if (IS_INTERNAL(thread) || list_empty(thread, list)) {
+        debug("del_thread: internal\n");
         return;
+    }
 
     lock(thread_list_lock);
-    list_del_init(&thread->list);
+    /* thread->list goes on the thread_list */
+    listp_del_init(thread, &thread_list, list);
     unlock(thread_list_lock);
     put_thread(thread);
 }
 
 void add_simple_thread (struct shim_simple_thread * thread)
 {
-    if (!list_empty(&thread->list))
+    if (!list_empty(thread, list))
         return;
 
     struct shim_simple_thread * tmp, * prev = NULL;
     lock(thread_list_lock);
 
     /* keep it sorted */
-    list_for_each_entry_reverse(tmp, &simple_thread_list, list) {
+    listp_for_each_entry_reverse(tmp, &simple_thread_list, list) {
         if (tmp->tid == thread->tid) {
             unlock(thread_list_lock);
             return;
@@ -410,17 +432,17 @@ void add_simple_thread (struct shim_simple_thread * thread)
     }
 
     get_simple_thread(thread);
-    list_add(&thread->list, prev ? &prev->list : &simple_thread_list);
+    listp_add_after(thread, prev, &simple_thread_list, list);
     unlock(thread_list_lock);
 }
 
 void del_simple_thread (struct shim_simple_thread * thread)
 {
-    if (list_empty(&thread->list))
+    if (list_empty(thread, list))
         return;
 
     lock(thread_list_lock);
-    list_del_init(&thread->list);
+    listp_del_init(thread, &simple_thread_list, list);
     unlock(thread_list_lock);
     put_simple_thread(thread);
 }
@@ -433,13 +455,14 @@ int check_last_thread (struct shim_thread * self)
     /* find out if there is any thread that is
        1) no current thread 2) in current vm
        3) still alive */
-    list_for_each_entry(tmp, &thread_list, list)
+    listp_for_each_entry(tmp, &thread_list, list) {
         if (tmp->tid &&
             (!self || tmp->tid != self->tid) && tmp->in_vm && tmp->is_alive) {
             debug("check_last_thread: thread %d is alive\n", tmp->tid);
             unlock(thread_list_lock);
             return tmp->tid;
         }
+    }
 
     debug("this is the only thread\n", self->tid);
     unlock(thread_list_lock);
@@ -459,7 +482,7 @@ relock:
 
     debug("walk_thread_list(callback=%p)\n", callback);
 
-    list_for_each_entry_safe(tmp, n, &thread_list, list) {
+    listp_for_each_entry_safe(tmp, n, &thread_list, list) {
         if (tmp->tid <= min_tid)
             continue;
         bool unlocked = false;
@@ -497,7 +520,7 @@ int walk_simple_thread_list (int (*callback) (struct shim_simple_thread *,
 relock:
     lock(thread_list_lock);
 
-    list_for_each_entry_safe(tmp, n, &simple_thread_list, list) {
+    listp_for_each_entry_safe(tmp, n, &simple_thread_list, list) {
         if (tmp->tid <= min_tid)
             continue;
         bool unlocked = false;
@@ -571,10 +594,10 @@ BEGIN_CP_FUNC(thread)
         new_thread = (struct shim_thread *) (base + off);
         memcpy(new_thread, thread, sizeof(struct shim_thread));
 
-        INIT_LIST_HEAD(&new_thread->children);
-        INIT_LIST_HEAD(&new_thread->siblings);
-        INIT_LIST_HEAD(&new_thread->exited_children);
-        INIT_LIST_HEAD(&new_thread->list);
+        INIT_LISTP(&new_thread->children);
+        INIT_LIST_HEAD(new_thread, siblings);
+        INIT_LISTP(&new_thread->exited_children);
+        INIT_LIST_HEAD(new_thread, list);
 
         new_thread->in_vm  = false;
         new_thread->parent = NULL;
@@ -609,7 +632,7 @@ BEGIN_CP_FUNC(thread)
         *objp = (void *) new_thread;
 }
 END_CP_FUNC(thread)
-
+    
 BEGIN_RS_FUNC(thread)
 {
     struct shim_thread * thread = (void *) (base + GET_CP_FUNC_ENTRY());
@@ -667,7 +690,7 @@ BEGIN_CP_FUNC(running_thread)
     }
 }
 END_CP_FUNC(running_thread)
-
+    
 int resume_wrapper (void * param)
 {
     struct shim_thread * thread = (struct shim_thread *) param;
@@ -694,7 +717,7 @@ BEGIN_RS_FUNC(running_thread)
     struct shim_thread * thread = (void *) (base + GET_CP_FUNC_ENTRY());
     struct shim_thread * cur_thread = get_cur_thread();
     thread->in_vm = true;
-
+    
     if (!thread->user_tcb)
         CP_REBASE(thread->tcb);
 
@@ -709,7 +732,7 @@ BEGIN_RS_FUNC(running_thread)
         thread->pal_handle = handle;
     } else {
         __libc_tcb_t * libc_tcb = (__libc_tcb_t *) thread->tcb;
-
+        
         if (libc_tcb) {
             shim_tcb_t * tcb = &libc_tcb->shim_tcb;
             assert(tcb->context.sp);
@@ -720,11 +743,11 @@ BEGIN_RS_FUNC(running_thread)
         } else {
             set_cur_thread(thread);
         }
-
+        
         thread->in_vm = thread->is_alive = true;
         thread->pal_handle = PAL_CB(first_thread);
     }
-
+    
     DEBUG_RS("tid=%d", thread->tid);
 }
 END_RS_FUNC(running_thread)
@@ -734,7 +757,7 @@ BEGIN_CP_FUNC(all_running_threads)
     struct shim_thread * thread;
     lock(thread_list_lock);
 
-    list_for_each_entry(thread, &thread_list, list) {
+    listp_for_each_entry(thread, &thread_list, list) {
         if (!thread->in_vm || !thread->is_alive)
             continue;
 

+ 48 - 34
LibOS/shim/src/bookkeep/shim_vma.c

@@ -31,7 +31,7 @@
 #include <shim_fs.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <asm/mman.h>
 #include <errno.h>
@@ -73,7 +73,8 @@ static inline void * __vma_malloc (size_t size)
 
 static MEM_MGR vma_mgr = NULL;
 
-static LIST_HEAD(vma_list);
+DEFINE_LISTP(shim_vma);
+static LISTP_TYPE(shim_vma) vma_list = LISTP_INIT;
 static LOCKTYPE vma_list_lock;
 
 static inline int test_vma_equal (struct shim_vma * tmp,
@@ -142,7 +143,7 @@ static inline void assert_vma (void)
     struct shim_vma * tmp;
     struct shim_vma * prev __attribute__((unused)) = NULL;
 
-    list_for_each_entry(tmp, &vma_list, list) {
+    listp_for_each_entry(tmp, &vma_list, list) {
         /* Assert we are really sorted */
         assert(tmp->length > 0);
         assert(!prev || prev->addr + prev->length <= tmp->addr);
@@ -190,7 +191,9 @@ void put_vma (struct shim_vma * vma)
 
 static void __remove_vma (struct shim_vma * vma)
 {
-    list_del(&vma->list);
+    /* We assume all vmas are on the vma_list.  
+     * Perhaps worth asserting?  */
+    listp_del(vma, &vma_list, list);
     put_vma(vma);
 }
 
@@ -229,6 +232,7 @@ static struct shim_vma * get_new_vma (void)
         return NULL;
 
     memset(tmp, 0, sizeof(struct shim_vma));
+    INIT_LIST_HEAD(tmp, list);
     REF_SET(tmp->ref_count, 1);
     return tmp;
 }
@@ -293,7 +297,7 @@ static int __bkeep_mmap (void * addr, uint64_t length,
         }
     } else {
         struct shim_vma * cont = NULL, * n; /* cont: continue to scan vmas */
-        struct list_head * pos = NULL; /* pos: position to add the vma */
+        struct shim_vma * pos = NULL; /* pos: position to add the vma */
 
         if (prev && prev->addr == addr &&
             prev->length <= length) { /* find a vma at the same addr */
@@ -317,15 +321,15 @@ static int __bkeep_mmap (void * addr, uint64_t length,
 
                 assert(prev->addr + prev->length <= addr);
                 cont = prev;
-                pos = &prev->list;
+                pos = prev;
             } else { /* has no precendent vma */
                 cont = tmp;
-                list_add(&tmp->list, &vma_list);
+                listp_add(tmp, &vma_list, list);
             }
         }
 
         if (cont)
-            list_for_each_entry_safe_continue(cont, n, &vma_list, list) {
+            listp_for_each_entry_safe_continue(cont, n, &vma_list, list) {
                 if (!test_vma_startin(cont, addr, length))
                     break;
 
@@ -349,7 +353,7 @@ static int __bkeep_mmap (void * addr, uint64_t length,
             }
 
         if (tmp && pos)
-            list_add(&tmp->list, pos);
+            list_add(tmp, pos, list);
     }
 
     tmp->addr = addr;
@@ -395,7 +399,7 @@ static int __bkeep_munmap (void * addr, uint64_t length, const int * flags)
 
     debug("bkeep_unmmap: %p-%p\n", addr, addr + length);
 
-    list_for_each_entry_safe(tmp, n, &vma_list, list) {
+    listp_for_each_entry_safe(tmp, n, &vma_list, list) {
         if (test_vma_equal (tmp, addr, length)) {
             if (!check_vma_flags(tmp, flags))
                 return -EACCES;
@@ -563,7 +567,7 @@ static int __bkeep_mprotect (void * addr, uint64_t length, int prot,
     while (length) {
         struct shim_vma * candidate = NULL;
 
-        list_for_each_entry(tmp, &vma_list, list) {
+        listp_for_each_entry(tmp, &vma_list, list) {
             if (test_vma_contain (tmp, addr, 1)) {
                 if (!check_vma_flags(tmp, flags))
                     return -EACCES;
@@ -690,17 +694,22 @@ void * get_unmapped_vma (uint64_t length, int flags)
     }
 
     do {
+        int found = 0;
         new->addr   = heap_top - length;
         new->length = length;
         new->flags  = flags|VMA_UNMAPPED;
         new->prot   = PROT_NONE;
 
-        list_for_each_entry_reverse(prev, &vma_list, list) {
-            if (new->addr >= prev->addr + prev->length)
+        listp_for_each_entry_reverse(prev, &vma_list, list) {
+            if (new->addr >= prev->addr + prev->length) {
+                found = 1;
                 break;
+            }
 
-            if (new->addr < heap_bottom)
+            if (new->addr < heap_bottom) {
+                found = 1;
                 break;
+            }
 
             if (prev->addr - heap_bottom < length) {
                 unlock(vma_list_lock);
@@ -712,7 +721,12 @@ void * get_unmapped_vma (uint64_t length, int flags)
                 new->addr = prev->addr - length;
         }
 
-        if (&prev->list == &vma_list) {
+
+        /* DEP 6/4/17: This case appears to be detecting whether you wrapped around the
+         * list wtihout finding anything. Let's add an explicit variable for
+         * this case, but keep the check for now to be safe. */
+        if (listp_empty(&vma_list)
+            || (!found && (prev == listp_last_entry(&vma_list, shim_vma, list)))) {
             prev = NULL;
             break;
         }
@@ -731,7 +745,7 @@ void * get_unmapped_vma (uint64_t length, int flags)
 
     assert(!prev || prev->addr + prev->length <= new->addr);
     get_vma(new);
-    list_add(&new->list, prev ? &prev->list : &vma_list);
+    listp_add_after(new, prev, &vma_list, list);
     debug("get unmapped: %p-%p\n", new->addr, new->addr + new->length);
     unlock(vma_list_lock);
     return new->addr;
@@ -782,7 +796,7 @@ void * get_unmapped_vma_for_cp (uint64_t length)
     new->flags  = flags;
     new->prot   = PROT_NONE;
 
-    list_add(&new->list, prev ? &prev->list : &vma_list);
+    listp_add_after(new, prev, &vma_list, list);
     unlock(vma_list_lock);
     return addr;
 }
@@ -794,7 +808,7 @@ static struct shim_vma * __lookup_overlap_vma (const void * addr, uint64_t lengt
 {
     struct shim_vma * tmp, * prev = NULL;
 
-    list_for_each_entry(tmp, &vma_list, list) {
+    listp_for_each_entry(tmp, &vma_list, list) {
         if (test_vma_overlap (tmp, addr, length)) {
             if (pprev)
                 *pprev = prev;
@@ -845,7 +859,7 @@ static struct shim_vma * __lookup_vma (const void * addr, uint64_t length)
     struct shim_vma * tmp;
     struct shim_vma * prev __attribute__((unused)) = NULL;
 
-    list_for_each_entry(tmp, &vma_list, list) {
+    listp_for_each_entry(tmp, &vma_list, list) {
         if (test_vma_equal(tmp, addr, length))
             return tmp;
 
@@ -862,7 +876,7 @@ static struct shim_vma * __lookup_supervma (const void * addr, uint64_t length,
 {
     struct shim_vma * tmp, * prev = NULL;
 
-    list_for_each_entry(tmp, &vma_list, list) {
+    listp_for_each_entry(tmp, &vma_list, list) {
         if (test_vma_contain(tmp, addr, length)) {
             if (pprev)
                 *pprev = prev;
@@ -906,20 +920,20 @@ struct shim_vma * next_vma (struct shim_vma * vma)
     lock(vma_list_lock);
 
     if (!tmp) {
-        if (!list_empty(&vma_list) &&
-            (tmp = list_first_entry(&vma_list, struct shim_vma, list)))
+        if (!listp_empty(&vma_list) &&
+            (tmp = listp_first_entry(&vma_list, struct shim_vma, list)))
             get_vma(tmp);
 
         unlock(vma_list_lock);
         return tmp;
     }
 
-    if (tmp->list.next == &vma_list) {
+    if (tmp->list.next == listp_first_entry(&vma_list, NULL, NULL)) {
         tmp = NULL;
-    } else if (tmp->list.next == &tmp->list) {
+    } else if (tmp->list.next == tmp) {
         struct shim_vma * tmp2;
         tmp = NULL;
-        list_for_each_entry(tmp2, &vma_list, list)
+        listp_for_each_entry(tmp2, &vma_list, list)
             if (tmp2->addr >= vma->addr) {
                 tmp = tmp2;
                 get_vma(tmp);
@@ -940,7 +954,7 @@ void __shrink_vmas (void)
 {
     struct shim_vma * vma, * n, * last;
 
-    list_for_each_entry_safe(vma, n, &vma_list, list) {
+    listp_for_each_entry_safe(vma, n, &vma_list, list) {
         if (!last)
             goto unmap;
 
@@ -975,7 +989,7 @@ int dump_all_vmas (struct shim_thread * thread, char * buf, uint64_t size)
     int cnt = 0;
     lock(vma_list_lock);
 
-    list_for_each_entry(vma, &vma_list, list) {
+    listp_for_each_entry(vma, &vma_list, list) {
         void * start = vma->addr, * end = vma->addr + vma->length;
 
         if ((vma->flags & (VMA_INTERNAL|VMA_UNMAPPED)) && !vma->comment[0])
@@ -1040,7 +1054,7 @@ void unmap_all_vmas (void)
     void * start = NULL, * end = NULL;
     lock(vma_list_lock);
 
-    list_for_each_entry_safe(tmp, n, &vma_list, list) {
+    listp_for_each_entry_safe(tmp, n, &vma_list, list) {
         /* a adhoc vma can never be removed */
         if (tmp->flags & VMA_INTERNAL)
             continue;
@@ -1103,7 +1117,7 @@ BEGIN_CP_FUNC(vma)
             DO_CP(handle, vma->file, &new_vma->file);
 
         REF_SET(new_vma->ref_count, 0);
-        INIT_LIST_HEAD(&new_vma->list);
+        INIT_LIST_HEAD(new_vma, list);
 
         void * need_mapped = vma->addr;
 
@@ -1203,13 +1217,13 @@ BEGIN_RS_FUNC(vma)
         if ((ret = __bkeep_munmap(vma->addr, vma->length, &vma->flags)) < 0)
             return ret;
 
-        if (prev->list.next == &tmp->list &&
+        if (prev->list.next == tmp &&
             tmp->addr < vma->addr)
             prev = tmp;
     }
 
     get_vma(vma);
-    list_add(&vma->list, prev ? &prev->list : &vma_list);
+    listp_add_after(vma, prev, &vma_list, list);
     assert_vma();
     SAVE_PROFILE_INTERVAL(vma_add_bookkeep);
 
@@ -1291,7 +1305,7 @@ BEGIN_CP_FUNC(all_vmas)
 
     __shrink_vmas();
 
-    list_for_each_entry(tmp, &vma_list, list)
+    listp_for_each_entry(tmp, &vma_list, list)
         if (!(tmp->flags & VMA_INTERNAL))
             nvmas++;
 
@@ -1302,7 +1316,7 @@ BEGIN_CP_FUNC(all_vmas)
 
     vmas = __alloca(sizeof(struct shim_vam *) * nvmas);
 
-    list_for_each_entry(tmp, &vma_list, list)
+    listp_for_each_entry(tmp, &vma_list, list)
         if (!(tmp->flags & VMA_INTERNAL)) {
             get_vma(tmp);
             vmas[cnt++] = tmp;
@@ -1322,7 +1336,7 @@ void debug_print_vma_list (void)
     sys_printf("vma bookkeeping:\n");
 
     struct shim_vma * vma;
-    list_for_each_entry(vma, &vma_list, list) {
+    listp_for_each_entry(vma, &vma_list, list) {
         const char * type = "", * name = "";
 
         if (vma->file) {

+ 58 - 44
LibOS/shim/src/fs/shim_dcache.c

@@ -31,13 +31,15 @@
 #include <shim_fs.h>
 #include <shim_checkpoint.h>
 
-#include <linux_list.h>
+#include <list.h>
 
-static LIST_HEAD(dcache_list);
-static LIST_HEAD(unused);
-static LIST_HEAD(persistent);
+/* As best I can tell, dentries are added to this list and then never touched
+ * again */
+/* Links to shim_dentry->list */
+static LISTP_TYPE(shim_dentry) dentry_list = LISTP_INIT;
 
-static struct hlist_head dcache_htable[DCACHE_HASH_SIZE] = { HLIST_HEAD_INIT };
+/* Attaches to shim_dentry->hlist */
+static LISTP_TYPE(shim_dentry) dcache_htable[DCACHE_HASH_SIZE] = { LISTP_INIT };
 
 LOCKTYPE dcache_lock;
 
@@ -87,10 +89,18 @@ static struct shim_dentry * alloc_dentry (void)
 
     dent->mode = NO_MODE;
 
-    INIT_HLIST_NODE(&dent->hlist);
-    INIT_LIST_HEAD(&dent->list);
-    INIT_LIST_HEAD(&dent->children);
-    INIT_LIST_HEAD(&dent->siblings);
+    INIT_LIST_HEAD(dent, hlist);
+    INIT_LIST_HEAD(dent, list);
+    INIT_LISTP(&dent->children);
+    INIT_LIST_HEAD(dent, siblings);
+
+    if (locked(dcache_lock)) {
+        listp_add(dent, &dentry_list, list);
+    } else {
+        lock(dcache_lock);
+        listp_add(dent, &dentry_list, list);
+        unlock(dcache_lock);
+    }
 
     return dent;
 }
@@ -135,13 +145,16 @@ int reinit_dcache (void)
 }
 
 /* remove from the hash table, so that a lookup will fail. */
-void __del_dcache (struct shim_dentry * dent)
+static void __del_dcache (struct shim_dentry * dent)
 {
     if (!(dent->state & DENTRY_HASHED))
         return;
 
+    /* DEP 5/15/17: I believe that, if a dentry is in the DENTRY_HASHED state,
+     * that the hash field is always valid. */
+    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
     dent->state &= ~DENTRY_HASHED;
-    hlist_del_init(&dent->hlist);
+    listp_del_init(dent, head, hlist);
 
 #ifdef DEBUG_DCACHE
     debug("del dcache %p(%s/%s) (mount = %p)\n",
@@ -152,13 +165,7 @@ void __del_dcache (struct shim_dentry * dent)
 
 static int __internal_put_dentry (struct shim_dentry * dent);
 
-void del_dcache (struct shim_dentry * dent)
-{
-    lock(dcache_lock);
-    __del_dcache(dent);
-    unlock(dcache_lock);
-}
-
+/* Release a dentry whose ref count has gone to zero. */
 static inline void __dput_dentry (struct shim_dentry * dent)
 {
     while (1) {
@@ -170,9 +177,15 @@ static inline void __dput_dentry (struct shim_dentry * dent)
         /* move the node to unused list unless it is persistent */
         if (!(dent->state & DENTRY_PERSIST)) {
             dent->state |= DENTRY_RECENTLY;
-            list_del(&dent->list);
-            INIT_LIST_HEAD(&dent->list);
-            list_add(&dent->list, &unused);
+            /* DEP: The only reference I see to this field is being placed on 
+             * the unused list. It seems that sometimes the dent is not
+             * on a list; just hack this for now; this code will be reworked
+             * soon anyway.
+             */
+
+            /* Chia-Che 10/17/17: Originally we place all the freed
+             * dentries on an unused list, now we just maintain a long list
+             * of all dentries. */
         }
 
         /* we don't delete the dentry from dcache because it might
@@ -189,8 +202,10 @@ kill:   {
             if (!parent)
                 break;
 
-            list_del(&dent->siblings); /* remove from parent's list of children */
-            dent->parent = NULL;
+            listp_del(dent, &parent->children, siblings); /* remove from parent's list of children */
+            listp_del(dent, &dentry_list, list);
+            /* we can free this dentry */
+            free_mem_obj_to_mgr(dentry_mgr, dent);
             dent = parent;
 
             if (__internal_put_dentry(dent))
@@ -275,7 +290,7 @@ void __set_parent_dentry (struct shim_dentry * child,
 
     assert(!child->parent);
     get_dentry(parent);
-    list_add_tail(&child->siblings, &parent->children);
+    listp_add_tail(child, &parent->children, siblings);
     child->parent = parent;
     parent->nchildren++;
 }
@@ -287,8 +302,9 @@ void __unset_parent_dentry (struct shim_dentry * child,
         return;
 
     assert(child->parent);
+    listp_del_init(child, &parent->children, siblings);
     child->parent = NULL;
-    list_del_init(&child->siblings);
+
     parent->nchildren--;
     put_dentry(parent);
 }
@@ -302,7 +318,7 @@ HASHTYPE hash_dentry (struct shim_dentry * start, const char * path, int len)
 
 void __add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr)
 {
-    struct hlist_head * head;
+    LISTP_TYPE(shim_dentry) * head;
 
     if (hashptr) {
         dent->rel_path.hash = *hashptr;
@@ -319,7 +335,7 @@ void __add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr)
 
 add_hash:
     head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
-    hlist_add_head(&dent->hlist, head);
+    listp_add(dent, head, hlist);
     dent->state |= DENTRY_HASHED;
 
 #ifdef DEBUG_DCACHE
@@ -342,12 +358,11 @@ __lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
 {
     HASHTYPE hash = hash_dentry(start, name, namelen);
     struct shim_dentry * dent, * found = NULL;
-    struct hlist_node * node;
-    struct hlist_head * head = &dcache_htable[DCACHE_HASH(hash)];
+    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(hash)];
 
     /* walk through all the nodes in the hash bucket, find the droids we're
        looking for */
-    hlist_for_each_entry(dent, node, head, hlist) {
+    listp_for_each_entry(dent, head, hlist) {
         if ((dent->state & DENTRY_MOUNTPOINT) ||
             dent->rel_path.hash != hash)
             continue;
@@ -404,23 +419,22 @@ lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
 int __del_dentry_tree (struct shim_dentry * root)
 {
     struct shim_dentry * this_parent = root;
-    struct list_head * next;
+    struct shim_dentry * next;
 
 repeat:
-    next = this_parent->children.next;
+    next = this_parent->children.first;
 
 resume:
-    while (next != &this_parent->children) {
-        struct list_head * tmp = next;
-        struct shim_dentry * d = list_entry(tmp, struct shim_dentry,
-                                            siblings);
-        next = tmp->next;
+    while (next != this_parent->children.first) {
+        struct shim_dentry *d, * tmp;
+        d = tmp = next;
+        next = tmp->siblings.next;
         if (d->state & DENTRY_MOUNTPOINT) {
             this_parent = d->mounted->root;
             goto repeat;
         }
 
-        if (!list_empty(&d->children)) {
+        if (!listp_empty(&d->children)) {
             this_parent = d;
             goto repeat;
         }
@@ -462,10 +476,10 @@ BEGIN_CP_FUNC(dentry)
 
         lock(dent->lock);
         *new_dent = *dent;
-        INIT_HLIST_NODE(&new_dent->hlist);
-        INIT_LIST_HEAD(&new_dent->list);
-        INIT_LIST_HEAD(&new_dent->children);
-        INIT_LIST_HEAD(&new_dent->siblings);
+        INIT_LIST_HEAD(new_dent, hlist);
+        INIT_LIST_HEAD(new_dent, list);
+        INIT_LISTP(&new_dent->children);
+        INIT_LIST_HEAD(new_dent, siblings);
         new_dent->data = NULL;
         clear_lock(new_dent->lock);
         REF_SET(new_dent->ref_count, 0);
@@ -511,8 +525,8 @@ BEGIN_RS_FUNC(dentry)
     if (dent->parent)
         __set_parent_dentry(dent, dent->parent);
 
-    struct hlist_head * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
-    hlist_add_head(&dent->hlist, head);
+    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
+    listp_add(dent, head, hlist);
     dent->state |= DENTRY_HASHED;
 
     DEBUG_RS("hash=%08x,path=%s,fs=%s", dent->rel_path.hash,

+ 10 - 8
LibOS/shim/src/fs/shim_fs.c

@@ -31,7 +31,7 @@
 #include <pal.h>
 #include <pal_error.h>
 #include <pal_debug.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <linux/fcntl.h>
 
@@ -70,7 +70,9 @@ static LOCKTYPE mount_mgr_lock;
 #include <memmgr.h>
 
 static MEM_MGR mount_mgr = NULL;
-static LIST_HEAD(mount_list);
+DEFINE_LISTP(shim_mount);
+/* Links to mount->list */
+static LISTP_TYPE(shim_mount) mount_list;
 static LOCKTYPE mount_list_lock;
 
 int init_fs (void)
@@ -286,7 +288,7 @@ int __mount_fs (struct shim_mount * mount, struct shim_dentry * dent)
 
     lock(mount_list_lock);
     get_mount(mount);
-    list_add_tail(&mount->list, &mount_list);
+    listp_add_tail(mount, &mount_list, list);
     unlock(mount_list_lock);
 
     do {
@@ -364,7 +366,7 @@ int walk_mounts (int (*walk) (struct shim_mount * mount, void * arg),
 
     lock(mount_list_lock);
 
-    list_for_each_entry_safe(mount, n, &mount_list, list) {
+    listp_for_each_entry_safe(mount, n, &mount_list, list) {
         if ((ret = (*walk) (mount, arg)) < 0)
             break;
 
@@ -382,7 +384,7 @@ struct shim_mount * find_mount_from_uri (const char * uri)
     int longest_path = 0;
 
     lock(mount_list_lock);
-    list_for_each_entry(mount, &mount_list, list) {
+    listp_for_each_entry(mount, &mount_list, list) {
         if (qstrempty(&mount->uri))
             continue;
 
@@ -439,7 +441,7 @@ BEGIN_CP_FUNC(mount)
         new_mount->data = NULL;
         new_mount->mount_point = NULL;
         new_mount->root = NULL;
-        INIT_LIST_HEAD(&new_mount->list);
+        INIT_LIST_HEAD(new_mount, list);
 
         DO_CP_IN_MEMBER(qstr, new_mount, path);
         DO_CP_IN_MEMBER(qstr, new_mount, uri);
@@ -481,7 +483,7 @@ BEGIN_RS_FUNC(mount)
     mount->fs_ops = fs->fs_ops;
     mount->d_ops = fs->d_ops;
 
-    list_add_tail(&mount->list, &mount_list);
+    listp_add_tail(mount, &mount_list, list);
 
     if (!qstrempty(&mount->path)) {
         DEBUG_RS("type=%s,uri=%s,path=%s", mount->type, qstrgetstr(&mount->uri),
@@ -496,7 +498,7 @@ BEGIN_CP_FUNC(all_mounts)
 {
     struct shim_mount * mount;
     lock(mount_list_lock);
-    list_for_each_entry(mount, &mount_list, list)
+    listp_for_each_entry(mount, &mount_list, list)
         DO_CP(mount, mount, NULL);
     unlock(mount_list_lock);
 

+ 1 - 1
LibOS/shim/src/fs/shim_namei.c

@@ -1046,7 +1046,7 @@ done_read:
 
         children = malloc(sizeof(struct shim_dentry *) * (nchildren + 1));
 
-        list_for_each_entry(child, &dent->children, siblings) {
+        listp_for_each_entry(child, &dent->children, siblings) {
             if (count >= nchildren)
                 break;
 

+ 19 - 17
LibOS/shim/src/ipc/shim_ipc.c

@@ -34,7 +34,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #define ipc_info_mgr_ALLOC  32
 #define PAGE_SIZE           allocsize
@@ -103,7 +103,7 @@ static struct shim_ipc_info * __get_new_ipc_info (IDTYPE vmid, const char * uri,
     if (uri)
         qstrsetstr(&info->uri, uri, len);
     REF_SET(info->ref_count, 1);
-    INIT_HLIST_NODE(&info->hlist);
+    INIT_LIST_HEAD(info, hlist);
     return info;
 }
 
@@ -183,20 +183,21 @@ void put_ipc_info (struct shim_ipc_info * info)
 #define CLIENT_HASH_MASK    (CLIENT_HASH_NUM - 1)
 #define CLIENT_HASH(vmid)   ((vmid) & CLIENT_HASH_MASK)
 
-static struct hlist_head client_table [CLIENT_HASH_NUM];
+/* Links to shim_ipc_info->hlist */
+DEFINE_LISTP(shim_ipc_info);
+static LISTP_TYPE(shim_ipc_info) client_table [CLIENT_HASH_NUM];
 
 struct shim_ipc_info *
 lookup_and_alloc_client (IDTYPE vmid, const char * uri)
 {
     struct shim_ipc_info * p;
-    struct hlist_head * head = client_table + CLIENT_HASH(vmid);
-    struct hlist_node * pos;
+    LISTP_TYPE(shim_ipc_info) *head = client_table + CLIENT_HASH(vmid);
     size_t len = strlen(uri);
 
     assert(vmid);
 
     lock(ipc_info_lock);
-    hlist_for_each_entry(p, pos, head, hlist)
+    listp_for_each_entry(p, head, hlist)
         if (p->vmid == vmid && !qstrcmpstr(&p->uri, uri, len)) {
             get_ipc_info(p);
             unlock(ipc_info_lock);
@@ -207,7 +208,7 @@ lookup_and_alloc_client (IDTYPE vmid, const char * uri)
     lock(ipc_info_lock);
     p = __get_new_ipc_info(vmid, uri, len);
     if (p) {
-        hlist_add_head(&p->hlist, head);
+        listp_add(p, head, hlist);
         get_ipc_info(p);
     }
     unlock(ipc_info_lock);
@@ -217,9 +218,11 @@ lookup_and_alloc_client (IDTYPE vmid, const char * uri)
 void put_client (struct shim_ipc_info * info)
 {
     lock(ipc_info_lock);
+    /* Look up the hash */
+    LISTP_TYPE(shim_ipc_info) *head = client_table + CLIENT_HASH(info->vmid);
     __put_ipc_info(info);
     if (REF_GET(info->ref_count) == 1) {
-        hlist_del_init(&info->hlist);
+        listp_del_init(info, head, hlist);
         __put_ipc_info(info);
     }
     unlock(ipc_info_lock);
@@ -229,13 +232,12 @@ struct shim_ipc_info * discover_client (struct shim_ipc_port * port,
                                         IDTYPE vmid)
 {
     struct shim_ipc_info * p;
-    struct hlist_head * head = client_table + CLIENT_HASH(vmid);
-    struct hlist_node * pos;
+    LISTP_TYPE(shim_ipc_info) * head = client_table + CLIENT_HASH(vmid);
 
     assert(vmid);
 
     lock(ipc_info_lock);
-    hlist_for_each_entry(p, pos, head, hlist)
+    listp_for_each_entry(p, head, hlist)
         if (p->vmid == vmid && !qstrempty(&p->uri)) {
             __get_ipc_info(p);
             unlock(ipc_info_lock);
@@ -320,7 +322,7 @@ int __init_ipc_msg_duplex (struct shim_ipc_msg_obj * msg, int code, int size,
 {
     __init_ipc_msg(&msg->msg, code, size, dest);
     msg->thread = NULL;
-    INIT_LIST_HEAD(&msg->list);
+    INIT_LIST_HEAD(msg, list);
     msg->retval = 0;
     msg->private = NULL;
     return 0;
@@ -383,9 +385,9 @@ int send_ipc_message (struct shim_ipc_msg * msg, struct shim_ipc_port * port)
 int close_ipc_message_duplex (struct shim_ipc_msg_obj * msg,
                               struct shim_ipc_port * port)
 {
-    if (port && !list_empty(&msg->list)) {
+    if (port && !list_empty(msg, list)) {
         lock(port->msgs_lock);
-        list_del_init(&msg->list);
+        listp_del_init(msg, &port->msgs, list);
         unlock(port->msgs_lock);
     }
 
@@ -409,7 +411,7 @@ int send_ipc_message_duplex (struct shim_ipc_msg_obj * msg,
     if (save) {
         lock(port->msgs_lock);
         msg->private = private_data;
-        list_add_tail(&msg->list, &port->msgs);
+        listp_add_tail(msg, &port->msgs, list);
         unlock(port->msgs_lock);
     }
 
@@ -429,10 +431,10 @@ struct shim_ipc_msg_obj * find_ipc_msg_duplex (struct shim_ipc_port * port,
 {
     struct shim_ipc_msg_obj * tmp, * found = NULL;
     lock(port->msgs_lock);
-    list_for_each_entry(tmp, &port->msgs, list)
+    listp_for_each_entry(tmp, &port->msgs, list)
         if (tmp->msg.seq == seq) {
             found = tmp;
-            list_del_init(&tmp->list);
+            listp_del_init(tmp, &port->msgs, list);
             break;
         }
     unlock(port->msgs_lock);

+ 42 - 40
LibOS/shim/src/ipc/shim_ipc_helper.c

@@ -34,7 +34,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #define PORT_MGR_ALLOC  32
 #define PAGE_SIZE       allocsize
@@ -43,14 +43,17 @@
 #include "memmgr.h"
 
 static MEM_MGR port_mgr;
-static LIST_HEAD(pobj_list);
+/* This points to a list of shim_ipc_port objects (by the list field) */
+DEFINE_LISTP(shim_ipc_port);
+static LISTP_TYPE(shim_ipc_port) pobj_list;
 
 #define PID_HASH_LEN   6
 #define PID_HASH_NUM   (1 << PID_HASH_LEN)
 #define PID_HASH_MASK  (PID_HASH_NUM - 1)
 #define PID_HASH(pid)  ((pid) & PID_HASH_MASK)
 
-static struct hlist_head ipc_port_pool [PID_HASH_NUM];
+/* This points to a list of shim_ipc_port objects (by the hlist field) */
+static LISTP_TYPE(shim_ipc_port) ipc_port_pool [PID_HASH_NUM];
 
 enum {
     HELPER_UNINITIALIZED, HELPER_DELAYED, HELPER_NOTALIVE,
@@ -217,10 +220,10 @@ static bool __add_ipc_port (struct shim_ipc_port * port, IDTYPE vmid,
         port->update = true;
     }
 
-    if (port->info.vmid && hlist_unhashed(&port->hlist)) {
-        struct hlist_head * head = &ipc_port_pool[PID_HASH(vmid)];
+    if (port->info.vmid && list_empty(port, hlist)) {
+        LISTP_TYPE(shim_ipc_port) * head = &ipc_port_pool[PID_HASH(vmid)];
         __get_ipc_port(port);
-        hlist_add_head(&port->hlist, head);
+        listp_add(port, head, hlist);
     }
 
     if (!(port->info.type & IPC_PORT_IFPOLL) && (type & IPC_PORT_IFPOLL))
@@ -242,22 +245,22 @@ static bool __add_ipc_port (struct shim_ipc_port * port, IDTYPE vmid,
     }
 
     if (need_restart) {
-        if (list_empty(&port->list)) {
+        if (list_empty(port, list)) {
             __get_ipc_port(port);
-            list_add(&port->list, &pobj_list);
+            listp_add(port, &pobj_list, list);
             port->recent = true;
         } else {
             if (!port->recent) {
-                list_del_init(&port->list);
-                list_add(&port->list, &pobj_list);
+                listp_del_init(port, &pobj_list, list);
+                listp_add(port, &pobj_list, list);
                 port->recent = true;
             }
         }
         return true;
     } else {
-        if (list_empty(&port->list)) {
+        if (list_empty(port, list)) {
             __get_ipc_port(port);
-            list_add_tail(&port->list, &pobj_list);
+            listp_add_tail(port, &pobj_list, list);
         }
         return false;
     }
@@ -289,9 +292,9 @@ static struct shim_ipc_port * __get_new_ipc_port (PAL_HANDLE hdl)
     memset(port, 0, sizeof(struct shim_ipc_port));
     port->pal_handle = hdl;
     port->update = true;
-    INIT_HLIST_NODE(&port->hlist);
-    INIT_LIST_HEAD(&port->list);
-    INIT_LIST_HEAD(&port->msgs);
+    INIT_LIST_HEAD(port, hlist);
+    INIT_LIST_HEAD(port, list);
+    INIT_LISTP(&port->msgs);
     REF_SET(port->ref_count, 1);
     create_lock(port->msgs_lock);
     return port;
@@ -306,12 +309,11 @@ void add_ipc_port_by_id (IDTYPE vmid, PAL_HANDLE hdl, int type,
     assert(!!hdl && PAL_GET_TYPE(hdl));
     lock(ipc_helper_lock);
 
-    struct hlist_head * head = vmid ? &ipc_port_pool[PID_HASH(vmid)] : NULL;
+    LISTP_TYPE(shim_ipc_port) * head = vmid ? &ipc_port_pool[PID_HASH(vmid)] : NULL;
     struct shim_ipc_port * tmp, * port = NULL;
-    struct hlist_node * pos;
 
     if (vmid)
-        hlist_for_each_entry(tmp, pos, head, hlist)
+        listp_for_each_entry(tmp, head, hlist)
             if (tmp->info.vmid == vmid && tmp->pal_handle == hdl) {
                 port = tmp;
                 __get_ipc_port(port);
@@ -319,7 +321,7 @@ void add_ipc_port_by_id (IDTYPE vmid, PAL_HANDLE hdl, int type,
             }
 
     if (!port)
-        list_for_each_entry(tmp, &pobj_list, list)
+        listp_for_each_entry(tmp, &pobj_list, list)
             if (tmp->pal_handle == hdl) {
                 port = tmp;
                 __get_ipc_port(port);
@@ -367,14 +369,16 @@ static bool __del_ipc_port (struct shim_ipc_port * port, int type)
     if (port->info.type & IPC_PORT_IFPOLL)
         need_restart = true;
 
-    if (!list_empty(&port->list)) {
-        list_del_init(&port->list);
+    if (!list_empty(port, list)) {
+        listp_del_init(port, &pobj_list, list);
         port->info.type &= IPC_PORT_IFPOLL;
         __put_ipc_port(port);
     }
 
-    if (!hlist_unhashed(&port->hlist)) {
-        hlist_del_init(&port->hlist);
+    if (!list_empty(port, hlist)) {
+        // Re-fetch head pointer
+        LISTP_TYPE(shim_ipc_port) * head = &ipc_port_pool[PID_HASH(port->info.vmid)];
+        listp_del_init(port, head, hlist);
         __put_ipc_port(port);
     }
 
@@ -395,14 +399,13 @@ void del_ipc_port (struct shim_ipc_port * port, int type)
 
 void del_ipc_port_by_id (IDTYPE vmid, int type)
 {
-    struct hlist_head * head = &ipc_port_pool[PID_HASH(vmid)];
-    struct shim_ipc_port * port;
-    struct hlist_node * pos, * n;
+    LISTP_TYPE(shim_ipc_port) * head = &ipc_port_pool[PID_HASH(vmid)];
+    struct shim_ipc_port * port, *n;
     bool need_restart = false;
 
     lock(ipc_helper_lock);
 
-    hlist_for_each_entry_safe(port, pos, n, head, hlist) {
+    listp_for_each_entry_safe(port, n, head, hlist) {
         debug("port %p (handle %p) for process %u in list %p\n",
               port, port->pal_handle, port->info.vmid, head);
 
@@ -443,11 +446,11 @@ void del_ipc_port_fini (struct shim_ipc_port * port, unsigned int exitcode)
 
     lock(port->msgs_lock);
 
-    if (!list_empty(&port->list)) {
+    if (!list_empty(port, list)) {
         struct shim_ipc_msg_obj * msg, * n;
 
-        list_for_each_entry_safe(msg, n, &port->msgs, list) {
-            list_del_init(&msg->list);
+        listp_for_each_entry_safe(msg, n, &port->msgs, list) {
+            listp_del_init(msg, &port->msgs, list);
             msg->retval = -ECONNRESET;
             if (msg->thread)
                 thread_wakeup(msg->thread);
@@ -465,11 +468,10 @@ void del_ipc_port_fini (struct shim_ipc_port * port, unsigned int exitcode)
 
 static struct shim_ipc_port * __lookup_ipc_port (IDTYPE vmid, int type)
 {
-    struct hlist_head * head = &ipc_port_pool[PID_HASH(vmid)];
+    LISTP_TYPE(shim_ipc_port) * head = &ipc_port_pool[PID_HASH(vmid)];
     struct shim_ipc_port * tmp;
-    struct hlist_node * pos;
-
-    hlist_for_each_entry(tmp, pos, head, hlist)
+    
+    listp_for_each_entry(tmp, head, hlist)
         if (tmp->info.vmid == vmid && (!type || tmp->info.type & type)) {
             debug("found port %p (handle %p) for process %u (type %04x)\n",
                   tmp, tmp->pal_handle, tmp->info.vmid, tmp->info.type);
@@ -505,7 +507,7 @@ void del_all_ipc_ports (int type)
 
     lock(ipc_helper_lock);
 
-    list_for_each_entry_safe(pobj, n, &pobj_list, list)
+    listp_for_each_entry_safe(pobj, n, &pobj_list, list)
         if (pobj->pal_handle && __del_ipc_port(pobj, type))
             need_restart = true;
 
@@ -537,7 +539,7 @@ int broadcast_ipc (struct shim_ipc_msg * msg, struct shim_ipc_port ** exclude,
     lock(ipc_helper_lock);
 
     int ntargets = 0;
-    list_for_each_entry(pobj, &pobj_list, list) {
+    listp_for_each_entry(pobj, &pobj_list, list) {
         debug("found port %p (handle %p) for process %u (type %04x)\n", pobj,
               pobj->pal_handle, pobj->info.vmid, pobj->info.type);
         if (pobj->info.type & target_type)
@@ -547,7 +549,7 @@ int broadcast_ipc (struct shim_ipc_msg * msg, struct shim_ipc_port ** exclude,
     struct shim_ipc_port ** targets = __alloca(sizeof(struct shim_ipc_port *)
                                                * ntargets);
     int i = 0;
-    list_for_each_entry(pobj, &pobj_list, list)
+    listp_for_each_entry(pobj, &pobj_list, list)
         if (pobj->info.type & target_type) {
             get_ipc_port(pobj);
             targets[i++] = pobj;
@@ -877,7 +879,7 @@ update_list:
         for (int i = 0 ; i < port_num ; i++) {
             struct shim_ipc_port * pobj = local_pobjs[i];
 
-            if (list_empty(&pobj->list)) {
+            if (list_empty(pobj, list)) {
                 if (polled == pobj->pal_handle) {
                     polled = NULL;
                     count = -1;
@@ -911,7 +913,7 @@ update_list:
         }
         port_num -= compact;
 
-        list_for_each_entry(pobj, &pobj_list, list) {
+        listp_for_each_entry(pobj, &pobj_list, list) {
             /* we only update among recently updated ports */
             if (!pobj->recent)
                 break;
@@ -1028,7 +1030,7 @@ int exit_with_ipc_helper (bool handover)
     if (handover) {
         handover = false;
         struct shim_ipc_port * pobj;
-        list_for_each_entry(pobj, &pobj_list, list)
+        listp_for_each_entry(pobj, &pobj_list, list)
             if (pobj->info.type & IPC_PORT_KEEPALIVE) {
                 handover = true;
                 break;

+ 71 - 49
LibOS/shim/src/ipc/shim_ipc_nsimpl.h

@@ -57,9 +57,10 @@ struct sub_map {
     struct subrange *   map[RANGE_SIZE];
 };
 
+DEFINE_LIST(range);
 struct range {
-    struct hlist_node   hlist;
-    struct list_head    list;
+    LIST_TYPE(range)    hlist;
+    LIST_TYPE(range)    list;
     int                 offset;
     struct shim_ipc_info *  owner;
     LEASETYPE           lease;
@@ -80,21 +81,27 @@ static LOCKTYPE range_map_lock;
 #define RANGE_HASH_MASK     (RANGE_HASH_NUM - 1)
 #define RANGE_HASH(off)     (((off - 1) / RANGE_SIZE) & RANGE_HASH_MASK)
 
-static struct hlist_head range_table [RANGE_HASH_NUM];
-static LIST_HEAD(owned_ranges);
-static LIST_HEAD(offered_ranges);
+/* This hash table organizes range structs by hlist */
+DEFINE_LISTP(range);
+static LISTP_TYPE(range) range_table [RANGE_HASH_NUM];
+/* These lists organizes range structs by list 
+ */
+static LISTP_TYPE(range) owned_ranges;
+static LISTP_TYPE(range) offered_ranges;
 static int nowned = 0;
 static int noffered = 0;
 static int nsubed = 0;
 
+DEFINE_LIST(ns_query);
 struct ns_query {
     IDTYPE                  dest;
     unsigned long           seq;
     struct shim_ipc_port *  port;
-    struct list_head        list;
+    LIST_TYPE(ns_query)     list;
 };
 
-static LIST_HEAD(ns_queries);
+DEFINE_LISTP(ns_query);
+static LISTP_TYPE(ns_query) ns_queries;
 
 static inline LEASETYPE get_lease (void)
 {
@@ -122,11 +129,10 @@ void CONCAT3(debug_print, NS, ranges) (void)
                 continue;
 
             int off = i * BITS + j;
-            struct hlist_head * head = range_table + RANGE_HASH(off);
+            LISTP_TYPE(range) * head = range_table + RANGE_HASH(off);
             struct range * tmp, * r = NULL;
-            struct hlist_node * pos;
 
-            hlist_for_each_entry(tmp, pos, head, hlist)
+            listp_for_each_entry(tmp, head, hlist)
                 if (tmp->offset == off) {
                     r = tmp;
                     break;
@@ -220,7 +226,7 @@ static bool __check_range_bitmap (int off)
 
 static struct range * __get_range (int off)
 {
-    struct hlist_head * head = range_table + RANGE_HASH(off);
+    LISTP_TYPE(range) * head = range_table + RANGE_HASH(off);
 
     if (!range_map || off >= range_map->map_size)
         return NULL;
@@ -229,9 +235,8 @@ static struct range * __get_range (int off)
         return NULL;
 
     struct range * r;
-    struct hlist_node * pos;
 
-    hlist_for_each_entry(r, pos, head, hlist)
+    listp_for_each_entry(r, head, hlist)
         if (r->offset == off)
             return r;
 
@@ -241,7 +246,7 @@ static struct range * __get_range (int off)
 static int __add_range (struct range * r, int off, IDTYPE owner,
                         const char * uri, LEASETYPE lease)
 {
-    struct hlist_head * head = range_table + RANGE_HASH(off);
+    LISTP_TYPE(range) * head = range_table + RANGE_HASH(off);
     int ret = 0;
 
     if (!range_map || range_map->map_size <= off) {
@@ -265,14 +270,22 @@ static int __add_range (struct range * r, int off, IDTYPE owner,
     ret = __set_range_bitmap(off, false);
     if (ret == -EEXIST) {
         struct range * tmp;
-        struct hlist_node * pos;
 
-        hlist_for_each_entry(tmp, pos, head, hlist)
+        listp_for_each_entry(tmp, head, hlist)
             if (tmp->offset == off) {
-                hlist_del(&tmp->hlist);
-                list_del(&tmp->list);
+                listp_del(tmp, head, hlist);
+
+                /* Chia-Che Tsai 10/17/17: only when tmp->owner is non-NULL,
+                 * and tmp->owner->vmid == cur_process.vmid, tmp is on the
+                 * owned list, otherwise it is an offered. */
+                if (tmp->owner && tmp->owner->vmid == cur_process.vmid)
+                    listp_del(tmp, &owned_ranges, list);
+                else
+                    listp_del(tmp, &offered_ranges, list);
+
                 if (tmp->owner)
                     put_client(tmp->owner);
+
                 r->used = tmp->used;
                 r->subranges = tmp->subranges;
                 free(tmp);
@@ -280,22 +293,23 @@ static int __add_range (struct range * r, int off, IDTYPE owner,
             }
     }
 
-    INIT_HLIST_NODE(&r->hlist);
-    hlist_add_head(&r->hlist, head);
-    INIT_LIST_HEAD(&r->list);
+    INIT_LIST_HEAD(r, hlist);
+    listp_add(r, head, hlist);
+    INIT_LIST_HEAD(r, list);
 
-    struct list_head * list = (owner == cur_process.vmid) ? &owned_ranges
+    LISTP_TYPE(range)* list = (owner == cur_process.vmid) ? &owned_ranges
                               : &offered_ranges;
-    struct list_head * prev = list;
+    struct range * prev = listp_first_entry(list, range, list);
     struct range * tmp;
 
-    list_for_each_entry(tmp, list, list) {
+
+    listp_for_each_entry(tmp, list, list) {
         if (tmp->offset >= off)
             break;
-        prev = &tmp->list;
+        prev = tmp;
     }
 
-    list_add(&r->list, prev);
+    listp_add_after(r, prev, list, list);
 
     if (owner == cur_process.vmid)
         nowned++;
@@ -527,8 +541,16 @@ int CONCAT3(del, NS, range) (IDTYPE idx)
 
     if (r->used)
         free(r->used);
-    hlist_del(&r->hlist);
-    list_del(&r->list);
+    // Re-acquire the head; kind of ugly
+    LISTP_TYPE(range) * head = range_table + RANGE_HASH(off);
+    listp_del(r, head, hlist);
+    /* Chia-Che Tsai 10/17/17: only when r->owner is non-NULL,
+     * and r->owner->vmid == cur_process.vmid, r is on the
+     * owned list, otherwise it is an offered. */
+    if (r->owner && r->owner->vmid == cur_process.vmid)
+        listp_del(r, &owned_ranges, list);
+    else
+        listp_del(r, &offered_ranges, list);
     put_ipc_info(r->owner);
     free(r);
 
@@ -611,7 +633,7 @@ IDTYPE CONCAT2(allocate, NS) (IDTYPE min, IDTYPE max)
     struct range * r;
     lock(range_map_lock);
 
-    list_for_each_entry (r, &owned_ranges, list) {
+    listp_for_each_entry (r, &owned_ranges, list) {
         if (max && idx >= max)
             break;
 
@@ -975,8 +997,8 @@ int NS_CALLBACK(findns) (IPC_CALLBACK_ARGS)
             query->seq  = msg->seq;
             get_ipc_port(port);
             query->port = port;
-            INIT_LIST_HEAD(&query->list);
-            list_add_tail(&query->list, &ns_queries);
+            INIT_LIST_HEAD(query, list);
+            listp_add_tail(query, &ns_queries, list);
         } else {
             ret = -ENOMEM;
         }
@@ -1036,8 +1058,8 @@ int NS_CALLBACK(tellns) (IPC_CALLBACK_ARGS)
 
     struct ns_query * query, * pos;
 
-    list_for_each_entry_safe(query, pos, &ns_queries, list) {
-        list_del(&query->list);
+    listp_for_each_entry_safe(query, pos, &ns_queries, list) {
+        listp_del(query, &ns_queries, list);
         NS_SEND(tellns)(query->port, query->dest, NS_LEADER, query->seq);
         put_ipc_port(query->port);
         free(query);
@@ -1478,7 +1500,7 @@ int NS_CALLBACK(queryall) (IPC_CALLBACK_ARGS)
 
     debug("ipc callback from %u: " NS_CODE_STR(QUERYALL) "\n", msg->src);
 
-    struct list_head * list = &offered_ranges;
+    LISTP_TYPE(range) * list = &offered_ranges;
     struct range * r;
     int ret;
 
@@ -1494,7 +1516,7 @@ int NS_CALLBACK(queryall) (IPC_CALLBACK_ARGS)
     int owner_offset = 0;
 
 retry:
-    list_for_each_entry (r, list, list) {
+    listp_for_each_entry (r, list, list) {
         struct shim_ipc_info * p = r->owner;
         int datasz = sizeof(struct ipc_ns_client) + p->uri.len;
         struct ipc_ns_client * owner = __alloca(datasz);
@@ -1649,24 +1671,25 @@ int NS_CALLBACK(answer) (IPC_CALLBACK_ARGS)
 #define KEY_HASH_NUM    (1 << KEY_HASH_LEN)
 #define KEY_HASH_MASK   (KEY_HASH_NUM - 1)
 
-static struct hlist_head key_map [KEY_HASH_NUM];
-
+DEFINE_LIST(key);
 struct key {
-    NS_KEY              key;
-    IDTYPE              id;
-    struct hlist_node   hlist;
+    NS_KEY                key;
+    IDTYPE                id;
+    LIST_TYPE(key)        hlist;
 };
+DEFINE_LISTP(key);
+static LISTP_TYPE(key) key_map [KEY_HASH_NUM];
+
 
 int CONCAT2(NS, add_key) (NS_KEY * key, IDTYPE id)
 {
-    struct hlist_head * head = &key_map[KEY_HASH(key) & KEY_HASH_MASK];
-    struct hlist_node * pos;
+    LISTP_TYPE(key) * head = &key_map[KEY_HASH(key) & KEY_HASH_MASK];
     struct key * k;
     int ret = -EEXIST;
 
     lock(range_map_lock);
 
-    hlist_for_each_entry(k, pos, head, hlist)
+    listp_for_each_entry(k, head, hlist)
         if (!KEY_COMP(&k->key, key))
             goto out;
 
@@ -1678,8 +1701,8 @@ int CONCAT2(NS, add_key) (NS_KEY * key, IDTYPE id)
 
     KEY_COPY(&k->key, key);
     k->id  = id;
-    INIT_HLIST_NODE(&k->hlist);
-    hlist_add_head(&k->hlist, head);
+    INIT_LIST_HEAD(k, hlist);
+    listp_add(k, head, hlist);
 
     debug("add key/id pair (%u, %u) to hash list: %p\n",
           KEY_HASH(key), id, head);
@@ -1691,18 +1714,17 @@ out:
 
 int CONCAT2(NS, get_key) (NS_KEY * key, bool delete)
 {
-    struct hlist_head * head = &key_map[KEY_HASH(key) & KEY_HASH_MASK];
-    struct hlist_node * pos;
+    LISTP_TYPE(key) * head = &key_map[KEY_HASH(key) & KEY_HASH_MASK];
     struct key * k;
     int id = -ENOENT;
 
     lock(range_map_lock);
 
-    hlist_for_each_entry(k, pos, head, hlist)
+    listp_for_each_entry(k, head, hlist)
         if (!KEY_COMP(&k->key, key)) {
             id = k->id;
             if (delete) {
-                hlist_del(&k->hlist);
+                listp_del(k, head, hlist);
                 free(k);
             }
             break;

+ 24 - 19
LibOS/shim/src/ipc/shim_ipc_pid.c

@@ -324,14 +324,14 @@ int get_all_pid_status (struct pid_status ** status)
     if (!bufsize)
         return -ENOMEM;
 
-    struct list_head * list = &offered_ranges;
+    LISTP_TYPE(range) * list = &offered_ranges;
     struct range * r;
     int ret;
 
     lock(range_map_lock);
 
 retry:
-    list_for_each_entry (r, list, list) {
+    listp_for_each_entry (r, list, list) {
         struct subrange * s = NULL;
         struct shim_ipc_info * p;
         int off, idx;
@@ -378,11 +378,12 @@ next_sub:
                 add_ipc_port_by_id(owner, pal_handle, type, NULL, &port);
 
             lock(range_map_lock);
-            list_for_each_entry(r, list, list)
+            listp_for_each_entry(r, list, list)
                 if (r->offset >= off)
                     break;
-
-            if (&r->list == list)
+            /* DEP 5/15/17: I believe this is checking if the list is empty */
+            //if (&r->list == list)
+            if (listp_empty(list))
                 break;
             if (r->offset > off)
                 goto next_range;
@@ -728,23 +729,27 @@ int ipc_pid_sendrpc_send (IDTYPE pid, IDTYPE sender, const void * buf,
     return ret;
 }
 
+DEFINE_LIST(rpcmsg);
 struct rpcmsg {
-    struct list_head list;
+    LIST_TYPE(rpcmsg) list;
     IDTYPE sender;
     int len;
     char payload[];
 };
 
+DEFINE_LIST(rpcreq);
 struct rpcreq {
-    struct list_head list;
+    LIST_TYPE(rpcreq) list;
     struct shim_thread * thread;
     IDTYPE sender;
     int len;
     void * buffer;
 };
 
-static LIST_HEAD(rpc_msgs);
-static LIST_HEAD(rpc_reqs);
+DEFINE_LISTP(rpcmsg);
+DEFINE_LISTP(rpcreq);
+static LISTP_TYPE(rpcmsg) rpc_msgs;
+static LISTP_TYPE(rpcreq) rpc_reqs;
 static LOCKTYPE rpc_queue_lock;
 
 int get_rpc_msg (IDTYPE * sender, void * buf, int len)
@@ -752,9 +757,9 @@ int get_rpc_msg (IDTYPE * sender, void * buf, int len)
     create_lock_runtime(&rpc_queue_lock);
     lock(rpc_queue_lock);
 
-    if (!list_empty(&rpc_msgs)) {
-        struct rpcmsg * m = list_first_entry(&rpc_msgs, struct rpcmsg, list);
-        list_del(&m->list);
+    if (!listp_empty(&rpc_msgs)) {
+        struct rpcmsg * m = listp_first_entry(&rpc_msgs, struct rpcmsg, list);
+        listp_del(m, &rpc_msgs, list);
         if (m->len < len)
             len = m->len;
         if (sender)
@@ -770,12 +775,12 @@ int get_rpc_msg (IDTYPE * sender, void * buf, int len)
         return -ENOMEM;
     }
 
-    INIT_LIST_HEAD(&r->list);
+    INIT_LIST_HEAD(r, list);
     r->sender = 0;
     r->len = len;
     r->buffer = buf;
     thread_setwait(&r->thread, NULL);
-    list_add_tail(&r->list, &rpc_reqs);
+    listp_add_tail(r, &rpc_reqs, list);
     unlock(rpc_queue_lock);
     thread_sleep(NO_TIMEOUT);
     put_thread(r->thread);
@@ -797,9 +802,9 @@ int ipc_pid_sendrpc_callback (IPC_CALLBACK_ARGS)
     create_lock_runtime(&rpc_queue_lock);
     lock(rpc_queue_lock);
 
-    if (!list_empty(&rpc_reqs)) {
-        struct rpcreq * r = list_first_entry(&rpc_reqs, struct rpcreq, list);
-        list_del(&r->list);
+    if (!listp_empty(&rpc_reqs)) {
+        struct rpcreq * r = listp_first_entry(&rpc_reqs, struct rpcreq, list);
+        listp_del(r, &rpc_reqs, list);
         if (msgin->len < r->len)
             r->len = msgin->len;
         r->sender = msgin->sender;
@@ -814,11 +819,11 @@ int ipc_pid_sendrpc_callback (IPC_CALLBACK_ARGS)
         goto out;
     }
 
-    INIT_LIST_HEAD(&m->list);
+    INIT_LIST_HEAD(m, list);
     m->sender = msgin->sender;
     m->len = msgin->len;
     memcpy(m->payload, msgin->payload, msgin->len);
-    list_add_tail(&m->list, &rpc_msgs);
+    listp_add_tail(m, &rpc_msgs, list);
 out:
     unlock(rpc_queue_lock);
     SAVE_PROFILE_INTERVAL(ipc_pid_sendrpc_callback);

+ 44 - 20
LibOS/shim/src/shim_async.c

@@ -28,19 +28,21 @@
 #include <shim_thread.h>
 
 #include <pal.h>
-#include <linux_list.h>
+#include <list.h>
 
+DEFINE_LIST(async_event);
 struct async_event {
-    IDTYPE              caller;
-    struct list_head    list;
-    void                (*callback) (IDTYPE caller, void * arg);
-    void *              arg;
-    PAL_HANDLE          object;
-    unsigned long       install_time;
-    unsigned long       expire_time;
+    IDTYPE                 caller;
+    LIST_TYPE(async_event) list;
+    void                   (*callback) (IDTYPE caller, void * arg);
+    void *                 arg;
+    PAL_HANDLE             object;
+    unsigned long          install_time;
+    unsigned long          expire_time;
 };
 
-static LIST_HEAD(async_list);
+DEFINE_LISTP(async_event);
+static LISTP_TYPE(async_event) async_list;
 
 enum {  HELPER_NOTALIVE, HELPER_ALIVE };
 
@@ -71,17 +73,38 @@ int install_async_event (PAL_HANDLE object, unsigned long time,
     lock(async_helper_lock);
 
     struct async_event * tmp;
-    struct list_head * prev = &async_list;
 
-    list_for_each_entry(tmp, &async_list, list) {
+    listp_for_each_entry(tmp, &async_list, list) {
         if (event->expire_time && tmp->expire_time > event->expire_time)
             break;
-        prev = &tmp->list;
     }
 
-    INIT_LIST_HEAD(&event->list);
-    list_add(&event->list, prev);
-
+    /* 
+     * man page of alarm system call :
+     * DESCRIPTION
+     * alarm() arranges for a SIGALRM signal to be delivered to the 
+	 * calling process in seconds seconds.
+     * If seconds is zero, any pending alarm is canceled.
+     * In any event any previously set alarm() is canceled.
+     */
+    if (!listp_empty(&async_list)) {
+        tmp = listp_first_entry(&async_list, struct async_event, list);
+        tmp = tmp->list.prev;
+        /*
+         * any previously set alarm() is canceled.
+         * There should be exactly only one timer pending
+         */
+		listp_del(tmp, &async_list, list);
+        free(tmp);
+    } else
+	   tmp = NULL;
+    
+    INIT_LIST_HEAD(event, list);
+    if (!time)    // If seconds is zero, any pending alarm is canceled.
+        free(event);
+    else
+        listp_add_tail(event, &async_list, list);   
+    
     unlock(async_helper_lock);
 
     if (atomic_read(&async_helper_state) == HELPER_NOTALIVE)
@@ -164,7 +187,8 @@ static void shim_async_helper (void * arg)
                 next_event->callback(next_event->caller, next_event->arg);
 
                 lock(async_helper_lock);
-                list_del(&next_event->list);
+                /* DEP: Events can only be on the async list */
+                listp_del(next_event, &async_list, list);
                 free(next_event);
                 goto update_list;
             }
@@ -187,7 +211,7 @@ update_status:
 
         lock(async_helper_lock);
 
-        list_for_each_entry_safe(tmp, n, &async_list, list) {
+        listp_for_each_entry_safe(tmp, n, &async_list, list) {
             if (tmp->object == polled) {
                 debug("async event trigger at %llu\n",
                       latest_time);
@@ -202,10 +226,10 @@ update_list:
         next_event = NULL;
         object_num = 0;
 
-        if (!list_empty(&async_list)) {
+        if (!listp_empty(&async_list)) {
             struct async_event * tmp, * n;
 
-            list_for_each_entry_safe(tmp, n, &async_list, list) {
+            listp_for_each_entry_safe(tmp, n, &async_list, list) {
                 if (tmp->object) {
                     local_objects[object_num + 1] = tmp->object;
                     object_num++;
@@ -221,7 +245,7 @@ update_list:
 
                 debug("async event trigger at %llu (expire at %llu)\n",
                       latest_time, tmp->expire_time);
-                list_del(&tmp->list);
+                listp_del(tmp, &async_list, list);
                 unlock(async_helper_lock);
                 tmp->callback(tmp->caller, tmp->arg);
                 free(tmp);

+ 9 - 8
LibOS/shim/src/shim_checkpoint.c

@@ -35,7 +35,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <stdarg.h>
 #include <asm/fcntl.h>
@@ -72,12 +72,14 @@ typedef uint16_t FASTHASHTYPE;
 
 #define CP_MAP_ENTRY_NUM 64
 
+DEFINE_LIST(cp_map_entry);
 struct cp_map_entry
 {
-    struct hlist_node hlist;
+    LIST_TYPE(cp_map_entry) hlist;
     struct shim_cp_map_entry entry;
 };
 
+DEFINE_LISTP(cp_map_entry);
 struct cp_map {
     struct cp_map_buffer {
         struct cp_map_buffer * next;
@@ -86,7 +88,7 @@ struct cp_map {
     } * buffers;
 
     struct hash_map {
-        struct hlist_head head[CP_HASH_SIZE];
+        LISTP_TYPE(cp_map_entry) head[CP_HASH_SIZE];
     } map;
 };
 
@@ -148,12 +150,11 @@ get_cp_map_entry (void * map, void * addr, bool create)
     struct cp_map * m = (struct cp_map *) map;
 
     FASTHASHTYPE hash = CP_HASH(addr);
-    struct hlist_head * head = &m->map.head[hash];
-    struct hlist_node * pos;
+    LISTP_TYPE(cp_map_entry) * head = &m->map.head[hash];
     struct cp_map_entry * tmp;
     struct shim_cp_map_entry * e = NULL;
 
-    hlist_for_each_entry(tmp, pos, head, hlist)
+    listp_for_each_entry(tmp, head, hlist)
         if (tmp->entry.addr == addr)
             e = &tmp->entry;
 
@@ -164,8 +165,8 @@ get_cp_map_entry (void * map, void * addr, bool create)
             buffer = extend_cp_map(m);
 
         struct cp_map_entry *new = &buffer->entries[buffer->cnt++];
-        INIT_HLIST_NODE(&new->hlist);
-        hlist_add_head(&new->hlist, head);
+        INIT_LIST_HEAD(new, hlist);
+        listp_add(new, head, hlist);
 
         new->entry.addr = addr;
         new->entry.off  = 0;

+ 32 - 49
LibOS/shim/src/sys/shim_epoll.c

@@ -53,6 +53,8 @@
 
 struct shim_mount epoll_builtin_fs;
 
+/* shim_epoll_fds are linked as a list (by the list field), 
+ * hanging off of a shim_epoll_handle (by the fds field) */
 struct shim_epoll_fd {
     FDTYPE                      fd;
     unsigned int                events;
@@ -61,8 +63,8 @@ struct shim_epoll_fd {
     struct shim_handle *        handle;
     struct shim_handle *        epoll;
     PAL_HANDLE                  pal_handle;
-    struct list_head            list;
-    struct list_head            back;
+    LIST_TYPE(shim_epoll_fd)    list;
+    LIST_TYPE(shim_epoll_fd)    back;
 };
 
 int shim_do_epoll_create1 (int flags)
@@ -83,7 +85,7 @@ int shim_do_epoll_create1 (int flags)
     epoll->pal_fds = malloc(sizeof(FDTYPE) * MAX_EPOLL_FDS);
     epoll->pal_handles = malloc(sizeof(PAL_HANDLE) * MAX_EPOLL_FDS);
     create_event(&epoll->event);
-    INIT_LIST_HEAD(&epoll->fds);
+    INIT_LISTP(&epoll->fds);
 
     int vfd = set_new_fd_handle(hdl, (flags & EPOLL_CLOEXEC) ? FD_CLOEXEC : 0,
                                 NULL);
@@ -106,9 +108,7 @@ static void update_epoll (struct shim_epoll_handle * epoll)
     int npals = 0;
     epoll->nread = 0;
 
-    debug("update pal handles of epoll handle %p\n", epoll);
-
-    list_for_each_entry(tmp, &epoll->fds, list) {
+    listp_for_each_entry(tmp, &epoll->fds, list) {
         if (!tmp->pal_handle)
             continue;
 
@@ -133,26 +133,27 @@ int delete_from_epoll_handles (struct shim_handle * handle)
     while (1) {
         lock(handle->lock);
 
-        if (list_empty(&handle->epolls)) {
+        if (listp_empty(&handle->epolls)) {
             unlock(handle->lock);
             break;
         }
 
-        struct shim_epoll_fd * epoll_fd = list_first_entry(&handle->epolls,
+        struct shim_epoll_fd * epoll_fd = listp_first_entry(&handle->epolls,
                                  struct shim_epoll_fd, back);
 
-        list_del(&epoll_fd->back);
+        listp_del(epoll_fd, &handle->epolls, back);
         unlock(handle->lock);
         put_handle(handle);
 
         struct shim_handle * epoll_hdl = epoll_fd->epoll;
+        struct shim_epoll_handle * epoll = &epoll_hdl->info.epoll;
 
         debug("delete handle %p from epoll handle %p\n", handle,
               &epoll_hdl->info.epoll);
 
         lock(epoll_hdl->lock);
 
-        list_del(&epoll_fd->list);
+        listp_del(epoll_fd, &epoll->fds, list);
         free(epoll_fd);
 
         epoll_hdl->info.epoll.nfds--;
@@ -185,7 +186,7 @@ int shim_do_epoll_ctl (int epfd, int op, int fd,
 
     switch (op) {
         case EPOLL_CTL_ADD: {
-            list_for_each_entry(epoll_fd, &epoll->fds, list)
+            listp_for_each_entry(epoll_fd, &epoll->fds, list)
                 if (epoll_fd->fd == fd) {
                     ret = -EEXIST;
                     goto out;
@@ -219,20 +220,14 @@ int shim_do_epoll_ctl (int epfd, int op, int fd,
             epoll_fd->epoll = epoll_hdl;
             epoll_fd->pal_handle = hdl->pal_handle;
 
-            lock(hdl->lock);
-            INIT_LIST_HEAD(&epoll_fd->back);
-            list_add_tail(&epoll_fd->back, &hdl->epolls);
-            unlock(hdl->lock);
-
-            get_handle(epoll_hdl);
-            INIT_LIST_HEAD(&epoll_fd->list);
-            list_add_tail(&epoll_fd->list, &epoll->fds);
+            INIT_LIST_HEAD(epoll_fd, list);
+            listp_add_tail(epoll_fd, &epoll->fds, list);
             epoll->nfds++;
             goto update;
         }
 
         case EPOLL_CTL_MOD: {
-            list_for_each_entry(epoll_fd, &epoll->fds, list)
+            listp_for_each_entry(epoll_fd, &epoll->fds, list)
                 if (epoll_fd->fd == fd) {
                     epoll_fd->events = event->events;
                     epoll_fd->data = event->data;
@@ -244,21 +239,11 @@ int shim_do_epoll_ctl (int epfd, int op, int fd,
         }
 
         case EPOLL_CTL_DEL: {
-            list_for_each_entry(epoll_fd, &epoll->fds, list)
+            listp_for_each_entry(epoll_fd, &epoll->fds, list)
                 if (epoll_fd->fd == fd) {
-                    struct shim_handle * hdl = epoll_fd->handle;
-                    lock(hdl->lock);
-                    list_del(&epoll_fd->back);
-                    put_handle(hdl);
-                    unlock(hdl->lock);
-
-                    debug("delete handle %p from epoll handle %p\n",
-                          hdl, epoll);
-
-                    list_del(&epoll_fd->list);
-                    put_handle(epoll_hdl);
+                    listp_del(epoll_fd, &epoll->fds, list);
+                    put_handle(epoll_fd->handle);
                     epoll->nfds--;
-
                     free(epoll_fd);
                     goto update;
                 }
@@ -334,7 +319,7 @@ retry:
     if (!DkStreamAttributesQuerybyHandle(polled, &attr))
         goto reply;
 
-    list_for_each_entry(epoll_fd, &epoll->fds, list)
+    listp_for_each_entry(epoll_fd, &epoll->fds, list)
         if (polled == epoll_fd->pal_handle) {
 
             debug("epoll: fd %d (handle %p) polled\n", epoll_fd->fd,
@@ -353,7 +338,7 @@ retry:
         }
 
 reply:
-    list_for_each_entry(epoll_fd, &epoll->fds, list) {
+    listp_for_each_entry(epoll_fd, &epoll->fds, list) {
         if (nevents == maxevents)
             break;
 
@@ -398,17 +383,17 @@ struct shim_mount epoll_builtin_fs = { .type = "epoll",
 
 BEGIN_CP_FUNC(epoll_fd)
 {
-    assert(size == sizeof(struct list_head));
+    assert(size == sizeof(LISTP_TYPE(shim_epoll_fd)));
 
-    struct list_head * old_list = (struct list_head *) obj;
-    struct list_head * new_list = (struct list_head *) objp;
+    LISTP_TYPE(shim_epoll_fd) * old_list = (LISTP_TYPE(shim_epoll_fd) *) obj;
+    LISTP_TYPE(shim_epoll_fd) * new_list = (LISTP_TYPE(shim_epoll_fd) *) objp;
     struct shim_epoll_fd * epoll_fd;
 
     debug("checkpoint epoll: %p -> %p (base = %p)\n", old_list, new_list, base);
 
-    INIT_LIST_HEAD(new_list);
+    INIT_LISTP(new_list);
 
-    list_for_each_entry(epoll_fd, old_list, list) {
+    listp_for_each_entry(epoll_fd, old_list, list) {
         ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_epoll_fd));
 
         struct shim_epoll_fd * new_epoll_fd =
@@ -419,8 +404,9 @@ BEGIN_CP_FUNC(epoll_fd)
         new_epoll_fd->data    = epoll_fd->data;
         new_epoll_fd->revents = epoll_fd->revents;
         new_epoll_fd->pal_handle = NULL;
-        list_add(new_list, &new_epoll_fd->list);
-        INIT_LIST_HEAD(&new_epoll_fd->back);
+        /* DEP XXX: Is the new_epoll_fd being added to new_list? */
+        //list_add(new_list, &new_epoll_fd->list);
+        listp_add(new_epoll_fd, new_list, list);
 
         DO_CP(handle, epoll_fd->handle, &new_epoll_fd->handle);
     }
@@ -431,20 +417,17 @@ END_CP_FUNC(epoll_fd)
 
 BEGIN_RS_FUNC(epoll_fd)
 {
-    struct list_head * list = (void *) (base + GET_CP_FUNC_ENTRY());
-    struct list_head * e;
+    LISTP_TYPE(shim_epoll_fd) * list = (void *) (base + GET_CP_FUNC_ENTRY());
+    struct shim_epoll_fd * epoll_fd;
 
     CP_REBASE(*list);
 
-    for (e = list->next ; e != list ; e = e->next) {
-        struct shim_epoll_fd * epoll_fd =
-                list_entry(e, struct shim_epoll_fd, list);
+    listp_for_each_entry(epoll_fd, list, list) {
 
         CP_REBASE(epoll_fd->handle);
         CP_REBASE(epoll_fd->back);
         epoll_fd->pal_handle = epoll_fd->handle->pal_handle;
-        list_add_tail(&epoll_fd->back, &epoll_fd->handle->epolls);
-        CP_REBASE(*e);
+        CP_REBASE(epoll_fd->list);
 
         DEBUG_RS("fd=%d,path=%s,type=%s,uri=%s",
                  epoll_fd->fd, qstrgetstr(&epoll_fd->handle->path),

+ 17 - 12
LibOS/shim/src/sys/shim_exec.c

@@ -206,6 +206,7 @@ static int migrate_execve (struct shim_cp_store * cpstore,
     return START_MIGRATE(cpstore, execve, thread, process, envp);
 }
 
+
 int shim_do_execve (const char * file, const char ** argv,
                     const char ** envp)
 {
@@ -220,12 +221,16 @@ int shim_do_execve (const char * file, const char ** argv,
 
     BEGIN_PROFILE_INTERVAL();
 
-    LIST_HEAD(shargs);
+    
+    DEFINE_LIST(sharg);
     struct sharg {
-        struct list_head list;
+        LIST_TYPE(sharg)  list;
         int len;
         char arg[0];
     };
+    DEFINE_LISTP(sharg);
+    LISTP_TYPE(sharg) shargs;
+    INIT_LISTP(&shargs);
 
 reopen:
 
@@ -277,7 +282,7 @@ err:
     }
 
     if (ret == -EINVAL) { /* it's a shebang */
-        LIST_HEAD(new_shargs);
+        LISTP_TYPE(sharg) new_shargs;
         struct sharg * next = NULL;
         bool ended = false, started = false;
         char buf[80];
@@ -316,8 +321,8 @@ err:
                         next->arg[l] = 0;
                     }
                     if (*c == ' ' || *c == '\n') {
-                        INIT_LIST_HEAD(&next->list);
-                        list_add_tail(&next->list, &new_shargs);
+                        INIT_LIST_HEAD(next, list);
+                        listp_add_tail(next, &new_shargs, list);
                         next = NULL;
                         s = c + 1;
                         if (*c == '\n') {
@@ -331,16 +336,16 @@ err:
 
         if (started) {
             if (next) {
-                INIT_LIST_HEAD(&next->list);
-                list_add_tail(&next->list, &new_shargs);
+                INIT_LIST_HEAD(next, list);
+                listp_add_tail(next, &new_shargs, list);
             }
 
             struct sharg * first =
-                list_first_entry(&new_shargs, struct sharg, list);
+                listp_first_entry(&new_shargs, struct sharg, list);
             assert(first);
             debug("detected as script: run by %s\n", first->arg);
             file = first->arg;
-            list_splice(&new_shargs, &shargs);
+            listp_splice(&new_shargs, &shargs, list, sharg);
             put_handle(exec);
             goto reopen;
         }
@@ -356,16 +361,16 @@ err:
 
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
 
-    if (!list_empty(&shargs)) {
+    if (!listp_empty(&shargs)) {
         struct sharg * sh;
         int shargc = 0, cnt = 0;
-        list_for_each_entry(sh, &shargs, list)
+        listp_for_each_entry(sh, &shargs, list)
             shargc++;
 
         const char ** new_argv =
                 __alloca(sizeof(const char *) * (argc + shargc + 1));
 
-        list_for_each_entry(sh, &shargs, list)
+        listp_for_each_entry(sh, &shargs, list)
             new_argv[cnt++] = sh->arg;
 
         for (cnt = 0 ; cnt < argc ; cnt++)

+ 6 - 5
LibOS/shim/src/sys/shim_exit.c

@@ -56,14 +56,14 @@ int thread_exit(struct shim_thread * self, bool send_ipc)
 
     if (!self->is_alive) {
         debug("thread %d is dead\n", self->tid);
-out:
+    out:
         unlock(self->lock);
         return 0;
     }
 
-#ifdef PROFILE
+    #ifdef PROFILE
     self->exit_time = GET_PROFILE_INTERVAL();
-#endif
+    #endif
 
     int exit_code = self->exit_code;
     self->is_alive = false;
@@ -83,8 +83,9 @@ out:
         debug("thread exits, notifying thread %d\n", parent->tid);
 
         lock(parent->lock);
-        list_del_init(&self->siblings);
-        list_add_tail(&self->siblings, &parent->exited_children);
+        listp_del_init(self, &parent->children, siblings);
+        listp_add_tail(self, &parent->exited_children, siblings);
+
         if (!self->in_vm) {
             debug("deliver SIGCHLD (thread = %d, exitval = %d)\n",
                   self->tid, exit_code);

+ 52 - 69
LibOS/shim/src/sys/shim_futex.c

@@ -32,7 +32,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <sys/syscall.h>
 #include <sys/mman.h>
@@ -43,13 +43,17 @@
 #define FUTEX_MIN_VALUE 0
 #define FUTEX_MAX_VALUE 255
 
+/* futex_waiters are linked off of shim_futex_handle by the waiters 
+ * listp */
 struct futex_waiter {
     struct shim_thread * thread;
     uint32_t bitset;
-    struct list_head list;
+    LIST_TYPE(futex_waiter) list;
 };
 
-static LIST_HEAD(futex_list);
+// Links shim_futex_handle by the list field
+DEFINE_LISTP(shim_futex_handle);
+static LISTP_TYPE(shim_futex_handle) futex_list = LISTP_INIT;
 static LOCKTYPE futex_list_lock;
 
 int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
@@ -68,7 +72,7 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
     create_lock_runtime(&futex_list_lock);
     lock(futex_list_lock);
 
-    list_for_each_entry(tmp, &futex_list, list)
+    listp_for_each_entry(tmp, &futex_list, list)
         if (tmp->uaddr == uaddr) {
             futex = tmp;
             break;
@@ -87,15 +91,14 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
         futex = &hdl->info.futex;
         futex->uaddr = uaddr;
         get_handle(hdl);
-        INIT_LIST_HEAD(&futex->waiters);
-        INIT_LIST_HEAD(&futex->list);
-        list_add_tail(&futex->list, &futex_list);
+        INIT_LISTP(&futex->waiters);
+        INIT_LIST_HEAD(futex, list);
+        listp_add_tail(futex, &futex_list, list);
     }
 
-    if (futex_op == FUTEX_WAKE_OP ||
-        futex_op == FUTEX_CMP_REQUEUE ||
-        futex_op == FUTEX_REQUEUE) {
-        list_for_each_entry(tmp, &futex_list, list)
+    if (futex_op == FUTEX_WAKE_OP || futex_op == FUTEX_REQUEUE ||
+            futex_op == FUTEX_CMP_REQUEUE) {
+        listp_for_each_entry(tmp, &futex_list, list)
             if (tmp->uaddr == uaddr2) {
                 futex2 = tmp;
                 break;
@@ -114,9 +117,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             futex2 = &hdl2->info.futex;
             futex2->uaddr = uaddr2;
             get_handle(hdl2);
-            INIT_LIST_HEAD(&futex2->waiters);
-            INIT_LIST_HEAD(&futex2->list);
-            list_add_tail(&futex2->list, &futex_list);
+            INIT_LISTP(&futex2->waiters);
+            INIT_LIST_HEAD(futex2, list);
+            listp_add_tail(futex2, &futex_list, list);
         }
 
         val2 = (uint32_t)(uint64_t) utime;
@@ -174,9 +177,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
 
             struct futex_waiter waiter;
             thread_setwait(&waiter.thread, NULL);
-            INIT_LIST_HEAD(&waiter.list);
+            INIT_LIST_HEAD(&waiter, list);
             waiter.bitset = bitset;
-            list_add_tail(&waiter.list, &futex->waiters);
+            listp_add_tail(&waiter, &futex->waiters, list);
 
             unlock(hdl->lock);
             ret = thread_sleep(timeout_us);
@@ -184,14 +187,16 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             if (ret == -EAGAIN)
                 ret = -ETIMEDOUT;
             lock(hdl->lock);
-            if (!list_empty(&waiter.list))
-                list_del(&waiter.list);
+            /* Chia-Che 10/17/17: FUTEX_WAKE should remove the waiter
+             * from the list; if not, we should remove it now. */
+            if (!list_empty(&waiter, list))
+                listp_del(&waiter, &futex->waiters, list);
             break;
         }
 
         case FUTEX_WAKE:
         case FUTEX_WAKE_BITSET: {
-            struct futex_waiter * waiter;
+            struct futex_waiter * waiter, * wtmp;
             int nwaken = 0;
             uint32_t bitset = (futex_op == FUTEX_WAKE_BITSET) ? val3 :
                               0xffffffff;
@@ -199,13 +204,13 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             debug("FUTEX_WAKE: %p (val = %d) count = %d mask = %08x\n",
                   uaddr, *uaddr, val, bitset);
 
-            list_for_each_entry(waiter, &futex->waiters, list) {
+            listp_for_each_entry_safe(waiter, wtmp, &futex->waiters, list) {
                 if (!(bitset & waiter->bitset))
                     continue;
 
                 debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n",
                       waiter->thread->tid, uaddr, *uaddr);
-                list_del_init(&waiter->list);
+                listp_del_init(waiter, &futex->waiters, list);
                 thread_wakeup(waiter->thread);
                 nwaken++;
                 if (nwaken >= val) break;
@@ -240,19 +245,13 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             }
 
             *(int *) uaddr2 = newval;
-            int cnt, nwaken = 0;
-            debug("FUTEX_WAKE: %p (val = %d) count = %d\n", uaddr, *uaddr, val);
-            for (cnt = 0 ; cnt < val ; cnt++) {
-                if (list_empty(&futex->waiters))
-                    break;
-
-                struct futex_waiter * waiter = list_entry(futex->waiters.next,
-                                                          struct futex_waiter,
-                                                          list);
-
-                debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n",
+            struct futex_waiter * waiter, * wtmp;
+            int nwaken = 0;
+            debug("FUTEX_WAKE_OP: %p (val = %d) count = %d\n", uaddr, *uaddr, val);
+            listp_for_each_entry_safe(waiter, wtmp, &futex->waiters, list) {
+                debug("FUTEX_WAKE_OP wake thread %d: %p (val = %d)\n",
                       waiter->thread->tid, uaddr, *uaddr);
-                list_del_init(&waiter->list);
+                listp_del_init(waiter, &futex->waiters, list);
                 thread_wakeup(waiter->thread);
                 nwaken++;
             }
@@ -264,17 +263,10 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
                 lock(hdl->lock);
                 debug("FUTEX_WAKE: %p (val = %d) count = %d\n", uaddr2,
                       *uaddr2, val2);
-                for (cnt = 0 ; cnt < val2 ; cnt++) {
-                    if (list_empty(&futex2->waiters))
-                        break;
-
-                    struct futex_waiter * waiter = list_entry(futex2->waiters.next,
-                                                              struct futex_waiter,
-                                                              list);
-
-                    debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n",
+                listp_for_each_entry_safe(waiter, wtmp, &futex2->waiters, list) {
+                    debug("FUTEX_WAKE_OP(2) wake thread %d: %p (val = %d)\n",
                           waiter->thread->tid, uaddr2, *uaddr2);
-                    list_del_init(&waiter->list);
+                    listp_del_init(waiter, &futex2->waiters, list);
                     thread_wakeup(waiter->thread);
                     nwaken++;
                 }
@@ -291,24 +283,21 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
 
         case FUTEX_REQUEUE: {
             assert(futex2);
-            int cnt;
-            for (cnt = 0 ; cnt < val ; cnt++) {
-                if (list_empty(&futex->waiters))
-                    break;
-
-                struct futex_waiter * waiter = list_entry(futex->waiters.next,
-                                                          struct futex_waiter,
-                                                          list);
-
-                list_del_init(&waiter->list);
+            struct futex_waiter * waiter, * wtmp;
+            int nwaken = 0;
+            listp_for_each_entry_safe(waiter, wtmp, &futex->waiters, list) {
+                listp_del_init(waiter, &futex->waiters, list);
                 thread_wakeup(waiter->thread);
+                nwaken++;
+                if (nwaken >= val)
+                    break;
             }
 
             lock(hdl2->lock);
-            list_splice_init(&futex->waiters, &futex2->waiters);
+            listp_splice_init(&futex->waiters, &futex2->waiters, list, futex_waiter);
             unlock(hdl2->lock);
             put_handle(hdl2);
-            ret = cnt;
+            ret = nwaken;
             break;
         }
 
@@ -374,7 +363,7 @@ void release_robust_list (struct robust_list_head * head)
 
         lock(futex_list_lock);
 
-        list_for_each_entry(tmp, &futex_list, list)
+        listp_for_each_entry(tmp, &futex_list, list)
             if (tmp->uaddr == futex_addr) {
                 futex = tmp;
                 break;
@@ -385,6 +374,7 @@ void release_robust_list (struct robust_list_head * head)
         if (!futex)
             continue;
 
+        struct futex_waiter * waiter, * wtmp;
         struct shim_handle * hdl =
             container_of(futex, struct shim_handle, info.futex);
         get_handle(hdl);
@@ -392,12 +382,8 @@ void release_robust_list (struct robust_list_head * head)
 
         debug("release robust list: %p\n", futex_addr);
         *(int *) futex_addr = 0;
-        while (!list_empty(&futex->waiters)) {
-            struct futex_waiter * waiter = list_entry(futex->waiters.next,
-                                                      struct futex_waiter,
-                                                      list);
-
-            list_del_init(&waiter->list);
+        listp_for_each_entry_safe(waiter, wtmp, &futex->waiters, list) {
+            listp_del_init(waiter, &futex->waiters, list);
             thread_wakeup(waiter->thread);
         }
 
@@ -416,7 +402,7 @@ void release_clear_child_id (int * clear_child_tid)
     struct shim_futex_handle * tmp, * futex = NULL;
     lock(futex_list_lock);
 
-    list_for_each_entry(tmp, &futex_list, list)
+    listp_for_each_entry(tmp, &futex_list, list)
         if (tmp->uaddr == (void *) clear_child_tid) {
             futex = tmp;
             break;
@@ -427,6 +413,7 @@ void release_clear_child_id (int * clear_child_tid)
     if (!futex)
         return;
 
+    struct futex_waiter * waiter, * wtmp;
     struct shim_handle * hdl =
             container_of(futex, struct shim_handle, info.futex);
     get_handle(hdl);
@@ -434,12 +421,8 @@ void release_clear_child_id (int * clear_child_tid)
 
     debug("release futex at %p\n", clear_child_tid);
     *clear_child_tid = 0;
-    while (!list_empty(&futex->waiters)) {
-        struct futex_waiter * waiter = list_entry(futex->waiters.next,
-                                                  struct futex_waiter,
-                                                  list);
-
-        list_del_init(&waiter->list);
+    listp_for_each_entry_safe(waiter, wtmp, &futex->waiters, list) {
+        listp_del_init(waiter, &futex->waiters, list);
         thread_wakeup(waiter->thread);
     }
 

+ 26 - 17
LibOS/shim/src/sys/shim_migrate.c

@@ -41,21 +41,30 @@
 
 #include <asm/mman.h>
 
-LIST_HEAD(cp_sessions);
+/* cp_session objects are on the cp_sessions list, by the list field */
+/* cp_threads are organized onto a list, handing off of the
+ * cp_session->registered_threads list. */
 
+DEFINE_LIST(cp_thread);
+struct cp_thread {
+    struct shim_thread *    thread;
+    LIST_TYPE(cp_thread)    list;
+};
+
+
+DEFINE_LIST(cp_session);
+DEFINE_LISTP(cp_thread);
 struct cp_session {
     IDTYPE                  sid;
     struct shim_handle *    cpfile;
-    struct list_head        registered_threads;
-    struct list_head        list;
+    LISTP_TYPE(cp_thread)   registered_threads;
+    LIST_TYPE(cp_session)   list;
     PAL_HANDLE              finish_event;
     struct shim_cp_store    cpstore;
 };
 
-struct cp_thread {
-    struct shim_thread *    thread;
-    struct list_head        list;
-};
+DEFINE_LISTP(cp_session);
+LISTP_TYPE(cp_session) cp_sessions;
 
 int create_checkpoint (const char * cpdir, IDTYPE * sid)
 {
@@ -65,8 +74,8 @@ int create_checkpoint (const char * cpdir, IDTYPE * sid)
 
     int ret = 0;
 
-    INIT_LIST_HEAD(&cpsession->registered_threads);
-    INIT_LIST_HEAD(&cpsession->list);
+    INIT_LISTP(&cpsession->registered_threads);
+    INIT_LIST_HEAD(cpsession, list);
     cpsession->finish_event = DkNotificationEventCreate(PAL_FALSE);
     cpsession->cpfile = NULL;
 
@@ -97,7 +106,7 @@ int create_checkpoint (const char * cpdir, IDTYPE * sid)
 
     struct cp_session * s;
     if (*sid) {
-        list_for_each_entry(s, &cp_sessions, list)
+        listp_for_each_entry(s, &cp_sessions, list)
             if (s->sid == *sid) {
                 ret = 0;
                 goto err_locked;
@@ -106,14 +115,14 @@ int create_checkpoint (const char * cpdir, IDTYPE * sid)
 retry:
         getrand(&cpsession->sid, sizeof(IDTYPE));
 
-        list_for_each_entry(s, &cp_sessions, list)
+        listp_for_each_entry(s, &cp_sessions, list)
             if (s->sid == cpsession->sid)
                 goto retry;
 
         *sid = cpsession->sid;
     }
 
-    list_add_tail(&cpsession->list, &cp_sessions);
+    listp_add_tail(cpsession, &cp_sessions, list);
     master_unlock();
     return 0;
 
@@ -133,13 +142,13 @@ static int finish_checkpoint (struct cp_session * session);
 static int check_thread (struct shim_thread * thread, void * arg,
                          bool * unlocked)
 {
-    struct list_head * registered = (struct list_head *) arg;
+    LISTP_TYPE(cp_thread) * registered = (LISTP_TYPE(cp_thread) *) arg;
     struct cp_thread * t;
 
     if (!thread->in_vm || !thread->is_alive)
         return 0;
 
-    list_for_each_entry(t, registered, list)
+    listp_for_each_entry(t, registered, list)
         if (t->thread == thread)
             return 0;
 
@@ -156,7 +165,7 @@ int join_checkpoint (struct shim_thread * thread, ucontext_t * context,
 
     master_lock();
 
-    list_for_each_entry(s, &cp_sessions, list)
+    listp_for_each_entry(s, &cp_sessions, list)
         if (s->sid == sid) {
             cpsession = s;
             break;
@@ -167,9 +176,9 @@ int join_checkpoint (struct shim_thread * thread, ucontext_t * context,
         return -EINVAL;
     }
 
-    INIT_LIST_HEAD(&cpthread.list);
+    INIT_LIST_HEAD(&cpthread, list);
     cpthread.thread = thread;
-    list_add_tail(&cpthread.list, &cpsession->registered_threads);
+    listp_add_tail(&cpthread, &cpsession->registered_threads, list);
 
     /* find out if there is any thread that is not registered yet */
     ret = walk_thread_list(&check_thread,

+ 31 - 27
LibOS/shim/src/sys/shim_msgget.c

@@ -33,7 +33,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 #include <errno.h>
 
 #define MSGQ_HASH_LEN     8
@@ -41,9 +41,12 @@
 #define MSGQ_HASH_MASK    (MSGQ_HASH_NUM - 1)
 #define MSGQ_HASH(idx)    ((idx) & MSGQ_HASH_MASK)
 
-static LIST_HEAD(msgq_list);
-static struct hlist_head msgq_key_hlist [MSGQ_HASH_NUM];
-static struct hlist_head msgq_qid_hlist [MSGQ_HASH_NUM];
+/* The msgq_list links shim_msg_handle objects by the list field.
+ * The msgq_key_hlist links them by key_hlist, and qid_hlist by qid_hlist */
+DEFINE_LISTP(shim_msg_handle);
+static LISTP_TYPE(shim_msg_handle) msgq_list;
+static LISTP_TYPE(shim_msg_handle) msgq_key_hlist [MSGQ_HASH_NUM];
+static LISTP_TYPE(shim_msg_handle) msgq_qid_hlist [MSGQ_HASH_NUM];
 static LOCKTYPE msgq_list_lock;
 
 static int __load_msg_persist (struct shim_msg_handle * msgq, bool readmsg);
@@ -57,18 +60,17 @@ DEFINE_PROFILE_CATAGORY(sysv_msg, );
 static int __add_msg_handle (unsigned long key, IDTYPE msqid, bool owned,
                              struct shim_msg_handle ** msghdl)
 {
-    struct hlist_head * key_head = (key != IPC_PRIVATE) ?
+    LISTP_TYPE(shim_msg_handle) * key_head = (key != IPC_PRIVATE) ?
                                    &msgq_key_hlist[MSGQ_HASH(key)] :
                                    NULL;
-    struct hlist_head * qid_head = msqid ?
+    LISTP_TYPE(shim_msg_handle) * qid_head = msqid ?
                                    &msgq_qid_hlist[MSGQ_HASH(msqid)] :
                                    NULL;
 
     struct shim_msg_handle * tmp;
-    struct hlist_node * pos;
 
     if (key_head)
-        hlist_for_each_entry(tmp, pos, key_head, key_hlist)
+        listp_for_each_entry(tmp, key_head, key_hlist)
             if (tmp->msqkey == key) {
                 if (tmp->msqid == msqid) {
                     if (msghdl)
@@ -79,7 +81,7 @@ static int __add_msg_handle (unsigned long key, IDTYPE msqid, bool owned,
             }
 
     if (qid_head)
-        hlist_for_each_entry(tmp, pos, qid_head, qid_hlist)
+        listp_for_each_entry(tmp, qid_head, qid_hlist)
             if (tmp->msqid == msqid) {
                 if (key)
                     tmp->msqkey = key;
@@ -111,19 +113,19 @@ static int __add_msg_handle (unsigned long key, IDTYPE msqid, bool owned,
     msgq->maxtypes  = INIT_MSG_TYPE_SIZE;
     msgq->types     = malloc(sizeof(struct msg_type) * INIT_MSG_TYPE_SIZE);
 
-    INIT_LIST_HEAD(&msgq->list);
+    INIT_LIST_HEAD(msgq, list);
     get_handle(hdl);
-    list_add_tail(&msgq->list, &msgq_list);
+    listp_add_tail(msgq, &msgq_list, list);
 
-    INIT_HLIST_NODE(&msgq->key_hlist);
+    INIT_LIST_HEAD(msgq, key_hlist);
     if (key_head) {
         get_handle(hdl);
-        hlist_add_head(&msgq->key_hlist, key_head);
+        listp_add(msgq, key_head, key_hlist);
     }
-    INIT_HLIST_NODE(&msgq->qid_hlist);
+    INIT_LIST_HEAD(msgq, qid_hlist);
     if (qid_head) {
         get_handle(hdl);
-        hlist_add_head(&msgq->qid_hlist, qid_head);
+        listp_add(msgq, qid_head, qid_hlist);
     }
 
     if (!msghdl) {
@@ -146,13 +148,12 @@ int add_msg_handle (unsigned long key, IDTYPE id, bool owned)
 struct shim_msg_handle * get_msg_handle_by_key (unsigned long key)
 {
 
-    struct hlist_head * key_head = &msgq_key_hlist[MSGQ_HASH(key)];
+    LISTP_TYPE(shim_msg_handle) * key_head = &msgq_key_hlist[MSGQ_HASH(key)];
     struct shim_msg_handle * tmp, * found = NULL;
-    struct hlist_node * pos;
 
     lock(msgq_list_lock);
 
-    hlist_for_each_entry(tmp, pos, key_head, key_hlist)
+    listp_for_each_entry(tmp, key_head, key_hlist)
         if (tmp->msqkey == key) {
             found = tmp;
             break;
@@ -167,13 +168,12 @@ struct shim_msg_handle * get_msg_handle_by_key (unsigned long key)
 
 struct shim_msg_handle * get_msg_handle_by_id (IDTYPE msqid)
 {
-    struct hlist_head * qid_head = &msgq_qid_hlist[MSGQ_HASH(msqid)];
+    LISTP_TYPE(shim_msg_handle) * qid_head = &msgq_qid_hlist[MSGQ_HASH(msqid)];
     struct shim_msg_handle * tmp, * found = NULL;
-    struct hlist_node * pos;
 
     lock(msgq_list_lock);
 
-    hlist_for_each_entry(tmp, pos, qid_head, qid_hlist)
+    listp_for_each_entry(tmp, qid_head, qid_hlist)
         if (tmp->msqid == msqid) {
             found = tmp;
             break;
@@ -243,14 +243,18 @@ static int __del_msg_handle (struct shim_msg_handle * msgq)
     struct shim_handle * hdl = MSG_TO_HANDLE(msgq);
 
     lock(msgq_list_lock);
-    list_del_init(&msgq->list);
+    listp_del_init(msgq, &msgq_list, list);
     put_handle(hdl);
-    if (!hlist_unhashed(&msgq->key_hlist)) {
-        hlist_del_init(&msgq->key_hlist);
+    if (!list_empty(msgq, key_hlist)) {
+        // DEP: Yuck, re-find the head; maybe we can do better...
+        LISTP_TYPE(shim_msg_handle) * key_head = &msgq_key_hlist[MSGQ_HASH(msgq->msqkey)];
+        listp_del_init(msgq, key_head, key_hlist);
         put_handle(hdl);
     }
-    if (!hlist_unhashed(&msgq->qid_hlist)) {
-        hlist_del_init(&msgq->qid_hlist);
+    if (!list_empty(msgq, qid_hlist)) {
+        // DEP: Yuck, re-find the head; maybe we can do better...
+        LISTP_TYPE(shim_msg_handle) * qid_head = &msgq_qid_hlist[MSGQ_HASH(msgq->msqid)];
+        listp_del_init(msgq, qid_head, qid_hlist);
         put_handle(hdl);
     }
     unlock(msgq_list_lock);
@@ -925,7 +929,7 @@ int store_all_msg_persist (void)
 
     lock(msgq_list_lock);
 
-    list_for_each_entry_safe(msgq, n, &msgq_list, list)
+    listp_for_each_entry_safe(msgq, n, &msgq_list, list)
         if (msgq->owned) {
             struct shim_handle * hdl = container_of(msgq, struct shim_handle,
                                                     info.msg);

+ 1 - 1
LibOS/shim/src/sys/shim_poll.c

@@ -33,7 +33,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <errno.h>
 

+ 63 - 50
LibOS/shim/src/sys/shim_semget.c

@@ -33,7 +33,7 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include <errno.h>
 
@@ -42,9 +42,12 @@
 #define SEM_HASH_MASK       (SEM_HASH_NUM - 1)
 #define SEM_HASH(idx)       ((idx) & SEM_HASH_MASK)
 
-static LIST_HEAD(sem_list);
-static struct hlist_head sem_key_hlist [SEM_HASH_NUM];
-static struct hlist_head sem_sid_hlist [SEM_HASH_NUM];
+/* The sem_list links shim_sem_handle objects by the list field.
+ * The sem_key_hlist links them by key_hlist, and qid_hlist by qid_hlist */
+DEFINE_LISTP(shim_sem_handle);
+static LISTP_TYPE(shim_sem_handle) sem_list;
+static LISTP_TYPE(shim_sem_handle) sem_key_hlist [SEM_HASH_NUM];
+static LISTP_TYPE(shim_sem_handle) sem_sid_hlist [SEM_HASH_NUM];
 static LOCKTYPE sem_list_lock;
 
 DEFINE_PROFILE_CATAGORY(sysv_sem, );
@@ -56,17 +59,16 @@ static int __add_sem_handle (unsigned long key, IDTYPE semid,
                              int nsems, bool owned,
                              struct shim_sem_handle ** semhdl)
 {
-    struct hlist_head * key_head = (key != IPC_PRIVATE) ?
+    LISTP_TYPE(shim_sem_handle) * key_head = (key != IPC_PRIVATE) ?
                                    &sem_key_hlist[SEM_HASH(key)] : NULL;
-    struct hlist_head * sid_head = semid ?
+    LISTP_TYPE(shim_sem_handle) * sid_head = semid ?
                                    &sem_sid_hlist[SEM_HASH(semid)] : NULL;
 
     struct shim_sem_handle * tmp;
-    struct hlist_node * pos;
     int ret = 0;
 
     if (key_head)
-        hlist_for_each_entry(tmp, pos, key_head, key_hlist)
+        listp_for_each_entry(tmp, key_head, key_hlist)
             if (tmp->semkey == key) {
                 if (tmp->semid == semid)
                     goto out;
@@ -74,7 +76,7 @@ static int __add_sem_handle (unsigned long key, IDTYPE semid,
             }
 
     if (sid_head)
-        hlist_for_each_entry(tmp, pos, sid_head, sid_hlist)
+        listp_for_each_entry(tmp, sid_head, sid_hlist)
             if (tmp->semid == semid) {
                 if (key)
                     tmp->semkey = key;
@@ -105,23 +107,23 @@ static int __add_sem_handle (unsigned long key, IDTYPE semid,
             tmp->sems[i].val = 0;
             tmp->sems[i].host_sem_id = 0;
             tmp->sems[i].host_sem = NULL;
-            INIT_LIST_HEAD(&tmp->sems[i].ops);
-            INIT_LIST_HEAD(&tmp->sems[i].next_ops);
+            INIT_LISTP(&tmp->sems[i].ops);
+            INIT_LISTP(&tmp->sems[i].next_ops);
         }
     }
 
-    INIT_LIST_HEAD(&tmp->migrated);
-    INIT_LIST_HEAD(&tmp->list);
+    INIT_LISTP(&tmp->migrated);
+    INIT_LIST_HEAD(tmp, list);
     get_handle(hdl);
-    list_add_tail(&tmp->list, &sem_list);
-    INIT_HLIST_NODE(&tmp->key_hlist);
+    listp_add_tail(tmp, &sem_list, list);
+    INIT_LIST_HEAD(tmp, key_hlist);
     if (key_head) {
         get_handle(hdl);
-        hlist_add_head(&tmp->key_hlist, key_head);
+        listp_add(tmp, key_head, key_hlist);
     }
     if (sid_head) {
         get_handle(hdl);
-        hlist_add_head(&tmp->sid_hlist, sid_head);
+        listp_add(tmp, sid_head, sid_hlist);
     }
 
 out:
@@ -148,13 +150,12 @@ int add_sem_handle (unsigned long key, IDTYPE id, int nsems, bool owned)
 
 struct shim_sem_handle * get_sem_handle_by_key (unsigned long key)
 {
-    struct hlist_head * key_head = &sem_key_hlist[SEM_HASH(key)];
+    LISTP_TYPE(shim_sem_handle) * key_head = &sem_key_hlist[SEM_HASH(key)];
     struct shim_sem_handle * tmp, * found = NULL;
-    struct hlist_node * pos;
 
     lock(sem_list_lock);
 
-    hlist_for_each_entry(tmp, pos, key_head, key_hlist)
+    listp_for_each_entry(tmp, key_head, key_hlist)
         if (tmp->semkey == key) {
             found = tmp;
             break;
@@ -169,13 +170,12 @@ struct shim_sem_handle * get_sem_handle_by_key (unsigned long key)
 
 struct shim_sem_handle * get_sem_handle_by_id (IDTYPE semid)
 {
-    struct hlist_head * sid_head = &sem_sid_hlist[SEM_HASH(semid)];
+    LISTP_TYPE(shim_sem_handle) * sid_head = &sem_sid_hlist[SEM_HASH(semid)];
     struct shim_sem_handle * tmp, * found = NULL;
-    struct hlist_node * pos;
 
     lock(sem_list_lock);
 
-    hlist_for_each_entry(tmp, pos, sid_head, sid_hlist)
+    listp_for_each_entry(tmp, sid_head, sid_hlist)
         if (tmp->semid == semid) {
             found = tmp;
             break;
@@ -203,14 +203,18 @@ static int __del_sem_handle (struct shim_sem_handle * sem)
     struct shim_handle * hdl = SEM_TO_HANDLE(sem);
 
     lock(sem_list_lock);
-    list_del_init(&sem->list);
+    listp_del_init(sem, &sem_list, list);
     put_handle(hdl);
-    if (!hlist_unhashed(&sem->key_hlist)) {
-        hlist_del_init(&sem->key_hlist);
+    if (!list_empty(sem, key_hlist)) {
+        // DEP: Yuck
+        LISTP_TYPE(shim_sem_handle) * key_head = &sem_key_hlist[SEM_HASH(sem->semkey)];
+        listp_del_init(sem, key_head, key_hlist);
         put_handle(hdl);
     }
-    if (!hlist_unhashed(&sem->sid_hlist)) {
-        hlist_del_init(&sem->sid_hlist);
+    if (!list_empty(sem, sid_hlist)) {
+        // DEP: Yuck
+        LISTP_TYPE(shim_sem_handle) * sid_head = &sem_sid_hlist[SEM_HASH(sem->semid)];
+        listp_del_init(sem, sid_head, sid_hlist);
         put_handle(hdl);
     }
     unlock(sem_list_lock);
@@ -320,8 +324,8 @@ int recover_sem_ownership (struct shim_sem_handle * sem,
         sem->sems[i].zcnt = backups[i].zcnt;
         sem->sems[i].ncnt = backups[i].ncnt;
         sem->sems[i].pid  = backups[i].pid;
-        INIT_LIST_HEAD(&sem->sems[i].ops);
-        INIT_LIST_HEAD(&sem->sems[i].next_ops);
+        INIT_LISTP(&sem->sems[i].ops);
+        INIT_LISTP(&sem->sems[i].next_ops);
     }
 
     for (int i = 0 ; i < nclients ; i++) {
@@ -337,8 +341,8 @@ int recover_sem_ownership (struct shim_sem_handle * sem,
         op->client.vmid = clients[i].vmid;
         op->client.port = NULL;
         op->client.seq  = clients[i].seq;
-        INIT_LIST_HEAD(&op->progress);
-        list_add_tail(&op->progress, &sem->migrated);
+        INIT_LIST_HEAD(op, progress);
+        listp_add_tail(op, &sem->migrated, progress);
     }
 
     sem->owned = true;
@@ -497,15 +501,17 @@ static bool __handle_sysv_sems (struct shim_sem_handle * sem)
 
     struct sem_obj * sobj;
     for (sobj = sem->sems ; sobj < &sem->sems[sem->nsems] ; sobj++)
-        list_splice_tail_init(&sobj->next_ops, &sobj->ops);
+        listp_splice_tail_init(&sobj->next_ops, &sobj->ops, progress, sem_ops);
 
     for (sobj = sem->sems ; sobj < &sem->sems[sem->nsems] ; sobj++) {
         struct sem_ops * sops, * n;
 
-        list_for_each_entry_safe(sops, n, &sobj->ops, progress) {
+        listp_for_each_entry_safe(sops, n, &sobj->ops, progress) {
             struct sembuf * op = &sops->ops[sops->stat.current];
             assert(op->sem_num == sobj->num);
-            assert(sops != n);
+            // first_iter is a variable defined by listp_for_each_entry_safe
+            // The second part of this assertion is only valid after the first attempt
+            assert(first_iter || (sops != n));
             if (sops->stat.completed)
                 goto send_result;
 again:
@@ -545,8 +551,10 @@ again:
 
             op = &sops->ops[sops->stat.current];
             if (op->sem_num != sobj->num) {
-                list_move_tail(&sops->progress,
-                               &sem->sems[op->sem_num].next_ops);
+                listp_move_tail(sops,
+                                &sem->sems[op->sem_num].next_ops,
+                                &sobj->ops,
+                                progress);
                 continue;
             }
 
@@ -555,7 +563,9 @@ failed:
             progressed = true;
             sops->stat.failed = true;
 send_result:
-            list_del_init(&sops->progress);
+            /* Chia-Che 10/17/17: If the code reaches this point, sops should
+             * still be in sobj->ops. */
+            listp_del_init(sops, &sobj->ops, progress);
             sem->nreqs--;
             if (!sops->client.vmid) {
                 setevent = true;
@@ -759,10 +769,10 @@ unowned:
     if (seq) {
         struct sem_ops * op;
 
-        list_for_each_entry(op, &sem->migrated, progress)
+        listp_for_each_entry(op, &sem->migrated, progress)
             if (op->client.vmid == (client ? client->vmid : cur_process.vmid)
                 && seq == op->client.seq) {
-                list_del_init(&op->progress);
+                listp_del_init(op, &sem->migrated, progress);
                 sem_ops = op;
                 stat = sem_ops->stat;
                 malloced = true;
@@ -797,7 +807,7 @@ unowned:
             sem_ops->client.vmid = 0;
             sem_ops->client.port = NULL;
             sem_ops->client.seq  = 0;
-            INIT_LIST_HEAD(&sem_ops->progress);
+            INIT_LIST_HEAD(sem_ops, progress);
             malloced = true;
             SAVE_PROFILE_INTERVAL(sem_alloc_semop);
         }
@@ -808,7 +818,7 @@ unowned:
             sem_ops->client.vmid = 0;
             sem_ops->client.port = NULL;
             sem_ops->client.seq  = 0;
-            INIT_LIST_HEAD(&sem_ops->progress);
+            INIT_LIST_HEAD(sem_ops, progress);
             SAVE_PROFILE_INTERVAL(sem_alloc_semop);
         }
     }
@@ -817,10 +827,10 @@ unowned:
     for (int i = 0 ; i < nsops ; i++)
         sem_ops->ops[i] = sops[i];
 
-    struct list_head * next_ops =
+    LISTP_TYPE(sem_ops) * next_ops =
             &sem->sems[sops[stat.current].sem_num].next_ops;
-    assert(list_empty(&sem_ops->progress));
-    list_add_tail(&sem_ops->progress, next_ops);
+    assert(list_empty(sem_ops, progress));
+    listp_add_tail(sem_ops, next_ops, progress);
     //check_list_head(next_ops);
     sem->nreqs++;
     SAVE_PROFILE_INTERVAL(sem_append_semop);
@@ -837,7 +847,10 @@ unowned:
     while (!sem_ops->stat.completed &&
            !sem_ops->stat.failed) {
         if (!sem->owned) {
-            list_del_init(&sem_ops->progress);
+            /* Chia-Che 10/17/17: sem_ops may move from semaphore to semaphore
+               base on its current state */
+            next_ops = &sem->sems[sem_ops->ops[sem_ops->stat.current].sem_num].next_ops;
+            listp_del_init(sem_ops, next_ops, progress);
             goto unowned;
         }
 
@@ -882,10 +895,10 @@ static int sem_balance_migrate (struct shim_handle * hdl,
         b->ncnt = sobj->ncnt;
         b->pid  = sobj->pid;
 
-        list_splice_tail(&sobj->next_ops, &sobj->ops);
+        listp_splice_tail(&sobj->next_ops, &sobj->ops, progress, sem_ops);
 
         struct sem_ops * sops;
-        list_for_each_entry(sops, &sobj->ops, progress) {
+        listp_for_each_entry(sops, &sobj->ops, progress) {
             assert(client_cnt < sem->nreqs);
             struct sem_client_backup * c = clients + (client_cnt)++;
             c->vmid = sops->client.vmid;
@@ -914,8 +927,8 @@ static int sem_balance_migrate (struct shim_handle * hdl,
 
     for (sobj = sem->sems ; sobj < &sem->sems[sem->nsems] ; sobj++) {
         struct sem_ops * sops, * n;
-        list_for_each_entry_safe(sops, n, &sobj->ops, progress) {
-            list_del_init(&sops->progress);
+        listp_for_each_entry_safe(sops, n, &sobj->ops, progress) {
+            listp_del_init(sops, &sobj->ops, progress);
             sem->nreqs--;
             sops->stat.failed = true;
             if (!sops->client.vmid)

+ 14 - 11
LibOS/shim/src/sys/shim_wait.c

@@ -70,12 +70,15 @@ block_pid:
             return 0;
         }
 
-        if (!list_empty(&thread->siblings)) {
+        if (!list_empty(thread, siblings)) {
+            debug("reaping thread %p\n", thread);
             struct shim_thread * parent = thread->parent;
             assert(parent);
 
             lock(parent->lock);
-            list_del_init(&thread->siblings);
+            /* DEP 5/15/17: These threads are exited */
+            assert(!thread->is_alive);
+            listp_del_init(thread, &thread->parent->exited_children, siblings);
             unlock(parent->lock);
 
             put_thread(parent);
@@ -89,8 +92,8 @@ block_pid:
 
     lock(cur->lock);
 
-    if (list_empty(&cur->children) &&
-        list_empty(&cur->exited_children)) {
+    if (listp_empty(&cur->children) &&
+        listp_empty(&cur->exited_children)) {
         unlock(cur->lock);
         return -ECHILD;
     }
@@ -98,7 +101,7 @@ block_pid:
     if (!(option & WNOHANG)) {
 block:
         if (cur->child_exit_event)
-            while (list_empty(&cur->exited_children)) {
+            while (listp_empty(&cur->exited_children)) {
                 unlock(cur->lock);
                 DkObjectsWaitAny(1, &cur->child_exit_event, NO_TIMEOUT);
                 lock(cur->lock);
@@ -109,16 +112,16 @@ block:
         if (pid == 0)
             pid = -cur->pgid;
 
-        list_for_each_entry(thread, &cur->exited_children, siblings)
+        listp_for_each_entry(thread, &cur->exited_children, siblings)
             if (thread->pgid == -pid)
                 goto found_child;
 
         if (!(option & WNOHANG))
             goto block;
     } else {
-        if (!list_empty(&cur->exited_children)) {
-            thread = list_first_entry(&cur->exited_children,
-                                      struct shim_thread, siblings);
+        if (!listp_empty(&cur->exited_children)) {
+            thread = listp_first_entry(&cur->exited_children,
+                                       struct shim_thread, siblings);
             goto found_child;
         }
     }
@@ -127,11 +130,11 @@ block:
     return 0;
 
 found_child:
-    list_del_init(&thread->siblings);
+    listp_del_init(thread, &cur->exited_children, siblings);
     put_thread(cur);
     thread->parent = NULL;
 
-    if (list_empty(&cur->exited_children))
+    if (listp_empty(&cur->exited_children))
         DkEventClear(cur->child_exit_event);
 
     unlock(cur->lock);

+ 1 - 1
LibOS/shim/test/regression/90_large-mmap.py

@@ -6,7 +6,7 @@ from regression import Regression
 loader = sys.argv[1]
 
 # Running Bootstrap
-regression = Regression(loader, "large-mmap", None, 120000)
+regression = Regression(loader, "large-mmap", None, 240000)
 
 regression.add_check(name="Ftruncate",
     check=lambda res: "large-mmap: ftruncate OK" in res[0].out)

+ 5 - 2
Pal/lib/api.h

@@ -105,10 +105,13 @@ int get_base_name (const char * path, char * buf, int size);
 
 /* Loading configs / manifests */
 
-#include <linux_list.h>
+#include <list.h>
 
+struct config;
+DEFINE_LISTP(config);
 struct config_store {
-    struct list_head root, entries;
+    LISTP_TYPE(config) root;
+    LISTP_TYPE(config) entries;
     void *           raw_data;
     int              raw_size;
     void *           (*malloc) (size_t);

+ 1 - 3
Pal/lib/crypto/adapters/mbedtls_adapter.c

@@ -1,6 +1,4 @@
-/* Copyright (C) 2017 Fortanix, Inc.
-
-   This file is part of Graphene Library OS.
+/* This file is part of Graphene Library OS.
 
    Graphene Library OS is free software: you can redistribute it and/or
    modify it under the terms of the GNU General Public License

+ 1 - 3
Pal/lib/crypto/adapters/wolfssl_adapter.c

@@ -1,6 +1,4 @@
-/* Copyright (C) 2017 Fortanix, Inc.
-
-   This file is part of Graphene Library OS.
+/* This file is part of Graphene Library OS.
 
    Graphene Library OS is free software: you can redistribute it and/or
    modify it under the terms of the GNU General Public License

+ 41 - 39
Pal/lib/graphene/config.c

@@ -24,16 +24,18 @@
  * a tree to lookup / access config values.
  */
 
-#include <linux_list.h>
+#include <list.h>
 #include <api.h>
 #include <pal_error.h>
 
+DEFINE_LIST(config);
 struct config {
     const char * key, * val;
     int klen, vlen;
     char * buf;
-    struct list_head list;
-    struct list_head children, siblings;
+    LIST_TYPE(config) list;
+    LISTP_TYPE(config) children;
+    LIST_TYPE(config) siblings; 
 };
 
 static int __add_config (struct config_store * store,
@@ -41,7 +43,7 @@ static int __add_config (struct config_store * store,
                          const char * val, int vlen,
                          struct config ** entry)
 {
-    struct list_head * list = &store->root;
+    LISTP_TYPE(config) * list = &store->root;
     struct config * e = NULL;
 
     while (klen) {
@@ -54,7 +56,7 @@ static int __add_config (struct config_store * store,
             if (token[len] == '.')
                 break;
 
-        list_for_each_entry(e, list, siblings)
+        listp_for_each_entry(e, list, siblings)
             if (e->klen == len && !memcmp(e->key, token, len))
                 goto next;
 
@@ -67,11 +69,11 @@ static int __add_config (struct config_store * store,
         e->val  = NULL;
         e->vlen = 0;
         e->buf  = NULL;
-        INIT_LIST_HEAD(&e->list);
-        list_add_tail(&e->list, &store->entries);
-        INIT_LIST_HEAD(&e->children);
-        INIT_LIST_HEAD(&e->siblings);
-        list_add_tail(&e->siblings, list);
+        INIT_LIST_HEAD(e, list);
+        listp_add_tail(e, &store->entries, list);
+        INIT_LISTP(&e->children);
+        INIT_LIST_HEAD(e, siblings);
+        listp_add_tail(e, list, siblings);
 
 next:
         if (len < klen)
@@ -81,7 +83,7 @@ next:
         list = &e->children;
     }
 
-    if (!e || e->val || !list_empty(&e->children))
+    if (!e || e->val || !listp_empty(&e->children))
         return -PAL_ERROR_INVAL;
 
     e->val  = val;
@@ -96,7 +98,7 @@ next:
 static struct config * __get_config (struct config_store * store,
                                      const char * key)
 {
-    struct list_head * list = &store->root;
+    LISTP_TYPE(config) * list = &store->root;
     struct config * e = NULL;
 
     while (*key) {
@@ -106,7 +108,7 @@ static struct config * __get_config (struct config_store * store,
             if (token[len] == '.')
                 break;
 
-        list_for_each_entry(e, list, siblings)
+        listp_for_each_entry(e, list, siblings)
             if (e->klen == len && !memcmp(e->key, token, len))
                 goto next;
 
@@ -146,10 +148,10 @@ int get_config_entries (struct config_store * store, const char * key,
     if (!e || e->val)
         return -PAL_ERROR_INVAL;
 
-    struct list_head * children = &e->children;
+    LISTP_TYPE(config) * children = &e->children;
     int nentries = 0;
 
-    list_for_each_entry(e, children, siblings) {
+    listp_for_each_entry(e, children, siblings) {
         if (e->klen >= size)
             return -PAL_ERROR_TOOLONG;
 
@@ -164,7 +166,7 @@ int get_config_entries (struct config_store * store, const char * key,
 }
 
 static int __del_config (struct config_store * store,
-                         struct list_head * root, const char * key)
+                         LISTP_TYPE(config) * root, const char * key)
 {
     struct config * e, * found = NULL;
     int len = 0;
@@ -172,7 +174,7 @@ static int __del_config (struct config_store * store,
         if (key[len] == '.')
             break;
 
-    list_for_each_entry(e, root, siblings)
+    listp_for_each_entry(e, root, siblings)
         if (e->klen == len && !memcmp(e->key, key, len)) {
             found = e;
             break;
@@ -187,15 +189,15 @@ static int __del_config (struct config_store * store,
         int ret = __del_config(store, &found->children, key + len + 1);
         if (ret < 0)
             return ret;
-        if (!list_empty(&found->children))
+        if (!listp_empty(&found->children))
             return 0;
     } else {
         if (!found->val)
             return -PAL_ERROR_INVAL;
     }
 
-    list_del(&found->siblings);
-    list_del(&found->list);
+    listp_del(found, root, siblings);
+    listp_del(found, &store->entries, list);
     if (found->buf)
         store->free(found->buf);
     store->free(found);
@@ -243,8 +245,8 @@ int read_config (struct config_store * store,
                  int (*filter) (const char * key, int ken),
                  const char ** errstring)
 {
-    INIT_LIST_HEAD(&store->root);
-    INIT_LIST_HEAD(&store->entries);
+    INIT_LISTP(&store->root);
+    INIT_LISTP(&store->entries);
 
     char * ptr = store->raw_data;
     char * ptr_end = store->raw_data + store->raw_size;
@@ -350,26 +352,26 @@ inval:
 int free_config (struct config_store * store)
 {
     struct config * e, * n;
-    list_for_each_entry_safe(e, n, &store->entries, list) {
+    listp_for_each_entry_safe(e, n, &store->entries, list) {
         if (e->buf)
             store->free(e->buf);
         store->free(e);
     }
 
-    INIT_LIST_HEAD(&store->root);
-    INIT_LIST_HEAD(&store->entries);
+    INIT_LISTP(&store->root);
+    INIT_LISTP(&store->entries);
     return 0;
 }
 
 static int __dup_config (const struct config_store * ss,
-                         const struct list_head * sr,
+                         const LISTP_TYPE(config) * sr,
                          struct config_store * ts,
-                         struct list_head * tr,
+                         LISTP_TYPE(config) * tr,
                          void ** data, int * size)
 {
     struct config * e, * new;
 
-    list_for_each_entry(e, sr, siblings) {
+    listp_for_each_entry(e, sr, siblings) {
         char * key = NULL, * val = NULL, * buf = NULL;
         int need = 0;
 
@@ -417,13 +419,13 @@ static int __dup_config (const struct config_store * ss,
         new->val  = val;
         new->vlen = e->vlen;
         new->buf  = buf;
-        INIT_LIST_HEAD(&new->list);
-        list_add_tail(&new->list, &ts->entries);
-        INIT_LIST_HEAD(&new->children);
-        INIT_LIST_HEAD(&new->siblings);
-        list_add_tail(&new->siblings, tr);
+        INIT_LIST_HEAD(new, list);
+        listp_add_tail(new, &ts->entries, list);
+        INIT_LISTP(&new->children);
+        INIT_LIST_HEAD(new, siblings);
+        listp_add_tail(new, tr, siblings);
 
-        if (!list_empty(&e->children)) {
+        if (!listp_empty(&e->children)) {
             int ret = __dup_config(ss, &e->children,
                                    ts, &new->children,
                                    data, size);
@@ -437,13 +439,13 @@ static int __dup_config (const struct config_store * ss,
 
 int copy_config (struct config_store * store, struct config_store * new_store)
 {
-    INIT_LIST_HEAD(&new_store->root);
-    INIT_LIST_HEAD(&new_store->entries);
+    INIT_LISTP(&new_store->root);
+    INIT_LISTP(&new_store->entries);
 
     struct config * e;
     int size = 0;
 
-    list_for_each_entry(e, &store->entries, list) {
+    listp_for_each_entry(e, &store->entries, list) {
         if (e->key)
             size += e->klen;
         if (e->val)
@@ -467,7 +469,7 @@ int copy_config (struct config_store * store, struct config_store * new_store)
 
 static int __write_config (void * f, int (*write) (void *, void *, int),
                            struct config_store * store,
-                           struct list_head * root,
+                           LISTP_TYPE(config) * root,
                            char * keybuf, int klen,
                            unsigned long * offset)
 {
@@ -476,7 +478,7 @@ static int __write_config (void * f, int (*write) (void *, void *, int),
     char * buf = NULL;
     int bufsz = 0;
 
-    list_for_each_entry(e, root, siblings)
+    listp_for_each_entry(e, root, siblings)
         if (e->val) {
             int total = klen + e->klen + e->vlen + 2;
 

+ 0 - 717
Pal/lib/linux_list.h

@@ -1,717 +0,0 @@
-/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
-/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
-
-/* This file may conflict with the list.h inside glibc */
-#if !defined(LINUX_LIST_H) && !defined(_LIST_H)
-#define LINUX_LIST_H
-#define _LIST_H 1
-
-/* This code is imported from linux kernel */
-
-#include <stddef.h>
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-#ifndef container_of
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr:	the pointer to the member.
- * @type:	the type of the container struct this is embedded in.
- * @member:	the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({			\
-	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
-	(type *)( (char *)__mptr - offsetof(type,member) );})
-
-#endif
-
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-
-struct list_head {
-        struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-        struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
-        list->next = list;
-        list->prev = list;
-}
-
-static inline int LIST_NOT_INIT(struct list_head *list)
-{
-        return list->next == 0 || list->prev == 0;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
-                              struct list_head *prev,
-                              struct list_head *next)
-{
-        next->prev = new;
-        new->next = next;
-        new->prev = prev;
-        prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-        __list_add(new, head, head->next);
-}
-
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-        __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
-        next->prev = prev;
-        prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
-        __list_del(entry->prev, entry->next);
-        entry->next = LIST_POISON1;
-        entry->prev = LIST_POISON2;
-}
-
-/**
- * list_replace - replace old entry by new one
- * @old : the element to be replaced
- * @new : the new element to insert
- *
- * If @old was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
-                                struct list_head *new)
-{
-        new->next = old->next;
-        new->next->prev = new;
-        new->prev = old->prev;
-        new->prev->next = new;
-}
-
-static inline void list_replace_init(struct list_head *old,
-                                     struct list_head *new)
-{
-        list_replace(old, new);
-        INIT_LIST_HEAD(old);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
-        __list_del(entry->prev, entry->next);
-        INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
-                                  struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add_tail(list, head);
-}
-
-/**
- * list_is_last - tests whether @list is the last entry in list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_last(const struct list_head *list,
-                               const struct list_head *head)
-{
-        return list->next == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
-        return head->next == head;
-}
-
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @head: the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
-{
-        struct list_head *next = head->next;
-        return (next == head) && (next == head->prev);
-}
-
-/**
- * list_rotate_left - rotate the list to the left
- * @head: the head of the list
- */
-static inline void list_rotate_left(struct list_head *head)
-{
-        struct list_head *first;
-
-        if (!list_empty(head)) {
-                first = head->next;
-                list_move_tail(first, head);
-        }
-}
-
-/**
- * list_is_singular - tests whether a list has just one entry.
- * @head: the list to test.
- */
-static inline int list_is_singular(const struct list_head *head)
-{
-        return !list_empty(head) && (head->next == head->prev);
-}
-
-static inline void __list_cut_position(struct list_head *list,
-                                       struct list_head *head, struct list_head *entry)
-{
-        struct list_head *new_first = entry->next;
-        list->next = head->next;
-        list->next->prev = list;
-        list->prev = entry;
-        entry->next = list;
-        head->next = new_first;
-        new_first->prev = head;
-}
-
-/**
- * list_cut_position - cut a list into two
- * @list: a new list to add all removed entries
- * @head: a list with entries
- * @entry: an entry within head, could be the head itself
- *	and if so we won't cut the list
- *
- * This helper moves the initial part of @head, up to and
- * including @entry, from @head to @list. You should
- * pass on @entry an element you know is on @head. @list
- * should be an empty list or a list you do not care about
- * losing its data.
- *
- */
-static inline void list_cut_position(struct list_head *list,
-                                     struct list_head *head, struct list_head *entry)
-{
-        if (list_empty(head))
-                return;
-        if (list_is_singular(head) &&
-            (head->next != entry && head != entry))
-                return;
-        if (entry == head)
-                INIT_LIST_HEAD(list);
-        else
-                __list_cut_position(list, head, entry);
-}
-
-static inline void __list_splice(const struct list_head *list,
-                                 struct list_head *prev,
-                                 struct list_head *next)
-{
-        struct list_head *first = list->next;
-        struct list_head *last = list->prev;
-
-        first->prev = prev;
-        prev->next = first;
-
-        last->next = next;
-        next->prev = last;
-}
-
-/**
- * list_splice - join two lists, this is designed for stacks
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(const struct list_head *list,
-                               struct list_head *head)
-{
-        if (!list_empty(list))
-                __list_splice(list, head, head->next);
-}
-
-/**
- * list_splice_tail - join two lists, each list being a queue
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice_tail(struct list_head *list,
-                                    struct list_head *head)
-{
-        if (!list_empty(list))
-                __list_splice(list, head->prev, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
-                                    struct list_head *head)
-{
-        if (!list_empty(list)) {
-                __list_splice(list, head, head->next);
-                INIT_LIST_HEAD(list);
-        }
-}
-
-/**
- * list_splice_tail_init - join two lists and reinitialise the emptied list
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * Each of the lists is a queue.
- * The list at @list is reinitialised
- */
-static inline void list_splice_tail_init(struct list_head *list,
-                                         struct list_head *head)
-{
-        if (!list_empty(list)) {
-                __list_splice(list, head->prev, head);
-                INIT_LIST_HEAD(list);
-        }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:	the &struct list_head pointer.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-        container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr:	the list head to take the element from.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
-        list_entry((ptr)->next, type, member)
-
-/**
- * list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
- */
-#define list_for_each(pos, head) \
-        for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
- */
-#define list_for_each_prev(pos, head) \
-        for (pos = (head)->prev; pos != (head); pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop cursor.
- * @n:		another &struct list_head to use as temporary storage
- * @head:	the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-        for (pos = (head)->next, n = pos->next; pos != (head); \
-             pos = n, n = pos->next)
-
-/**
- * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop cursor.
- * @n:		another &struct list_head to use as temporary storage
- * @head:	the head for your list.
- */
-#define list_for_each_prev_safe(pos, n, head) \
-        for (pos = (head)->prev, n = pos->prev; \
-             pos != (head); pos = n, n = pos->prev)
-
-/**
- * list_for_each_entry	-	iterate over list of given type
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member)                      \
-        for (pos = list_entry((head)->next, typeof(*pos), member);  \
-             &pos->member != (head);    \
-             pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member)              \
-        for (pos = list_entry((head)->prev, typeof(*pos), member);  \
-             &pos->member != (head);    \
-             pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @pos:	the type * to use as a start point
- * @head:	the head of the list
- * @member:	the name of the list_struct within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
- */
-#define list_prepare_entry(pos, head, member) \
-        ((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member)                 \
-        for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
-             &pos->member != (head);        \
-             pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue_reverse - iterate backwards from the given point
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Start to iterate over list of given type backwards, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue_reverse(pos, head, member)         \
-        for (pos = list_entry(pos->member.prev, typeof(*pos), member);  \
-             &pos->member != (head);        \
-             pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member)                     \
-        for (; &pos->member != (head);      \
-             pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member)                  \
-        for (pos = list_entry((head)->next, typeof(*pos), member),      \
-             n = list_entry(pos->member.next, typeof(*pos), member);    \
-             &pos->member != (head);                                    \
-             pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_continue - continue list iteration safe against removal
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing after current point,
- * safe against removal of list entry.
- */
-#define list_for_each_entry_safe_continue(pos, n, head, member)         \
-        for (pos = list_entry(pos->member.next, typeof(*pos), member),  \
-             n = list_entry(pos->member.next, typeof(*pos), member);    \
-             &pos->member != (head);                                    \
-             pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_from - iterate over list from current point safe against removal
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type from current point, safe against
- * removal of list entry.
- */
-#define list_for_each_entry_safe_from(pos, n, head, member)             \
-        for (n = list_entry(pos->member.next, typeof(*pos), member);    \
-             &pos->member != (head);                                    \
-             pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate backwards over list of given type, safe against removal
- * of list entry.
- */
-#define list_for_each_entry_safe_reverse(pos, n, head, member)          \
-        for (pos = list_entry((head)->prev, typeof(*pos), member),      \
-             n = list_entry(pos->member.prev, typeof(*pos), member);    \
-             &pos->member != (head);                                    \
-             pos = n, n = list_entry(n->member.prev, typeof(*n), member))
-
-#define check_list_head(head)                                           \
-        do {                                                            \
-            struct list_head * pos;                                     \
-                                                                        \
-            list_for_each(pos, head) {                                  \
-                assert(pos->prev != pos && pos->next != pos);           \
-                assert(pos->prev->next == pos);                         \
-                assert(pos->next->prev == pos);                         \
-            }                                                           \
-        } while (0)
-
-/*
- * Double linked lists with a single pointer list head.
- * Mostly useful for hash tables where the two pointer list head is
- * too wasteful.
- * You lose the ability to access the tail in O(1).
- */
-
-struct hlist_head {
-        struct hlist_node *first;
-};
-
-struct hlist_node {
-        struct hlist_node *next, **pprev;
-};
-
-#define HLIST_HEAD_INIT { .first = NULL }
-#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
-#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
-static inline void INIT_HLIST_NODE(struct hlist_node *h)
-{
-        h->next = NULL;
-        h->pprev = NULL;
-}
-
-static inline int hlist_unhashed(const struct hlist_node *h)
-{
-        return !h->pprev;
-}
-
-static inline int hlist_empty(const struct hlist_head *h)
-{
-        return !h->first;
-}
-
-static inline void __hlist_del(struct hlist_node *n)
-{
-        struct hlist_node *next = n->next;
-        struct hlist_node **pprev = n->pprev;
-        *pprev = next;
-        if (next)
-                next->pprev = pprev;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
-        __hlist_del(n);
-        n->next = LIST_POISON1;
-        n->pprev = LIST_POISON2;
-}
-
-static inline void hlist_del_init(struct hlist_node *n)
-{
-        if (!hlist_unhashed(n)) {
-                __hlist_del(n);
-                INIT_HLIST_NODE(n);
-        }
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
-        struct hlist_node *first = h->first;
-        n->next = first;
-        if (first)
-                first->pprev = &n->next;
-        h->first = n;
-        n->pprev = &h->first;
-}
-
-/* next must be != NULL */
-static inline void hlist_add_before(struct hlist_node *n,
-                                    struct hlist_node *next)
-{
-        n->pprev = next->pprev;
-        n->next = next;
-        next->pprev = &n->next;
-        *(n->pprev) = n;
-}
-
-static inline void hlist_add_after(struct hlist_node *n,
-                                   struct hlist_node *next)
-{
-        next->next = n->next;
-        n->next = next;
-        next->pprev = &n->next;
-
-        if(next->next)
-                next->next->pprev  = &next->next;
-}
-
-/*
- * Move a list from one list head to another. Fixup the pprev
- * reference of the first entry if it exists.
- */
-static inline void hlist_move_list(struct hlist_head *old,
-                                   struct hlist_head *new)
-{
-        new->first = old->first;
-        if (new->first)
-                new->first->pprev = &new->first;
-        old->first = NULL;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define hlist_for_each(pos, head) \
-        for (pos = (head)->first; pos ; pos = pos->next)
-
-#define hlist_for_each_safe(pos, n, head) \
-        for (pos = (head)->first; pos ; pos = n)
-
-/**
- * hlist_for_each_entry	- iterate over list of given type
- * @tpos:	the type * to use as a loop cursor.
- * @pos:	the &struct hlist_node to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry(tpos, pos, head, member)                   \
-        for (pos = (head)->first; pos &&                                \
-             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});   \
-             pos = pos->next)
-
-/**
- * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @tpos:	the type * to use as a loop cursor.
- * @pos:	the &struct hlist_node to use as a loop cursor.
- * @member:	the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_continue(tpos, pos, member)                \
-        for (pos = (pos)->next; pos &&                                  \
-             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});   \
-             pos = pos->next)
-
-/**
- * hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @tpos:	the type * to use as a loop cursor.
- * @pos:	the &struct hlist_node to use as a loop cursor.
- * @member:	the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_from(tpos, pos, member)                    \
-        for (; pos &&                                                   \
-             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});   \
-             pos = pos->next)
-
-/**
- * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos:	the type * to use as a loop cursor.
- * @pos:	the &struct hlist_node to use as a loop cursor.
- * @n:		another &struct hlist_node to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member)           \
-        for (pos = (head)->first;                                       \
-             pos && ({ n = pos->next; 1; }) &&                          \
-             ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});   \
-             pos = n)
-
-#endif

+ 324 - 0
Pal/lib/list-test.c

@@ -0,0 +1,324 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+/* Copyright (C) 2017 University of North Carolina at Chapel Hill and
+   Fortanix, Inc.
+   This file is part of Graphene Library OS.
+
+   Graphene Library OS is free software: you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   Graphene Library OS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Unit test for the new list implementation */
+
+#include "list.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+DEFINE_LIST(simple);
+struct simple {
+    int idx;
+    LIST_TYPE(simple) list;
+};
+
+DEFINE_LISTP(simple);
+static LISTP_TYPE(simple) list_in_the_sky = LISTP_INIT;
+static LISTP_TYPE(simple) list_in_the_basement = LISTP_INIT;
+
+/* Use some static arrays to assert expected list contents */
+int sol1[7] = {1, 2, 3, 4, 5, 6, 7};
+int sol2[10] = {1, 2, 25, 3, 4, 45, 5, 6, 65, 7};
+int sol3[17] = {1, 2, 25, 3, 4, 45, 5, 6, 65, 7, 8, 9, 10, 11, 12, 13, 14};
+int sol4[20] = {1, 2, 25, 3, 4, 45, 5, 6, 65, 7, 8, 85, 9, 10, 105, 11, 12, 125, 13, 14};
+int sol5[7] = {7, 6, 5, 4, 3, 2, 1};
+int sol6[4] = {7, 5, 3, 1};
+int sol7[10] = {7, 5, 3, 1, 13, 12, 11, 10, 9, 8};
+int sol8[17] = {7, 5, 3, 1, 13, 12, 11, 10, 9, 8, 20, 19, 18, 17, 16, 15, 14};
+
+void print_list(LISTP_TYPE(simple) *listp) {
+    struct simple *tmp;
+    printf("Beginning of list\n");
+    listp_for_each_entry(tmp, listp, list) {
+        printf("List element %d\n", tmp->idx);
+    }
+    printf("End of list\n\n");
+}
+
+void assert_list(LISTP_TYPE(simple) *listp, int len, int *array, int stop_early_ok) {
+    int j = 0;
+    struct simple *tmp;
+    int stop_early = 0;
+    check_list_head(struct simple *, listp, list);
+    listp_for_each_entry(tmp, listp, list) {
+        if (j >= len) {
+            stop_early = 1;
+            break;
+        }
+        assert(tmp->idx == array[j]);
+        j++;
+    }
+    assert(j >= len);
+    if (!stop_early)
+        assert(tmp == listp->first);
+    else
+        assert(stop_early_ok);
+}
+    
+
+void print_list_reverse(LISTP_TYPE(simple) *listp) {
+    struct simple *tmp;
+    printf("Beginning of list\n");
+    listp_for_each_entry_reverse(tmp, listp, list) {
+        printf("List element %d\n", tmp->idx);
+    }
+    printf("End of list\n\n");
+}
+
+
+int main() {
+    int i;
+    struct simple *tmp, *tmp2, *n;
+
+    assert(listp_empty(&list_in_the_sky));
+
+    /* Try printing an empty list */
+    print_list(&list_in_the_sky);
+
+    /* Test adding things to the listp */
+    for (i = 0; i < 7; i++) {
+        tmp = malloc(sizeof(struct simple));
+        tmp->idx = 7 - i;
+        INIT_LIST_HEAD(tmp, list);
+        assert(list_empty(tmp, list));
+        listp_add(tmp, &list_in_the_sky, list);
+        assert(!list_empty(tmp, list));
+        assert_list(&list_in_the_sky, i, &sol1[6-i], 1);
+    }
+    assert(!listp_empty(&list_in_the_sky));
+
+    assert_list(&list_in_the_sky, 7, sol1, 0);
+    
+    /* Test list_add  - i.e., adding things in the middle of the list*/
+    listp_for_each_entry_safe(tmp, n, &list_in_the_sky, list) {
+        if ((tmp->idx % 2) == 0) {
+            tmp2 = malloc(sizeof(struct simple));
+            tmp2->idx = (tmp->idx * 10) + 5; 
+            INIT_LIST_HEAD(tmp2, list);
+            assert(list_empty(tmp2, list));
+            list_add(tmp2, tmp, list);
+            assert(!list_empty(tmp2, list));
+        }
+    }
+
+    //print_list(&list_in_the_sky);
+    //print_list_reverse(&list_in_the_sky);
+    assert_list(&list_in_the_sky, 10, sol2, 0);
+
+    /* Try adding some integers to the tail of the list */
+    for (i = 0; i < 7; i++) {
+        tmp = malloc(sizeof(struct simple));
+        tmp->idx = 8 + i;
+        INIT_LIST_HEAD(tmp, list);
+        assert(list_empty(tmp, list));
+        listp_add_tail(tmp, &list_in_the_sky, list);
+        assert(!list_empty(tmp, list));
+    }
+    assert(!listp_empty(&list_in_the_sky));
+
+    assert_list(&list_in_the_sky, 17, sol3, 0);
+
+    /* Test list_add_tail by adding ints from end */
+    listp_for_each_entry(tmp, &list_in_the_sky, list) {
+        if (tmp->idx <= 7 || tmp->idx > 20)
+            continue;
+
+        if ((tmp->idx % 2) == 1) {
+            tmp2 = malloc(sizeof(struct simple));
+            tmp2->idx = ((tmp->idx - 1) * 10) + 5; 
+            INIT_LIST_HEAD(tmp2, list);
+            assert(list_empty(tmp2, list));
+            list_add_tail(tmp2, tmp, list);
+            assert(!list_empty(tmp2, list));
+        }
+    }
+
+    //print_list(&list_in_the_sky);
+    //print_list_reverse(&list_in_the_sky);
+    assert_list(&list_in_the_sky, 20, sol4, 0);
+
+    printf("Deletion test starting\n\n");
+    
+    /* Test list deletion and safe iteration by destroying the list*/
+    listp_for_each_entry_safe(tmp, n, &list_in_the_sky, list) {
+        listp_del(tmp, &list_in_the_sky, list);
+        free(tmp);
+        //print_list(&list_in_the_sky);
+    }
+    assert(listp_empty(&list_in_the_sky));
+
+    printf("Deletion test Ending\n\n");
+    
+    /* Rebuild the list */
+    for (i = 0; i < 7; i++) {
+        tmp = malloc(sizeof(struct simple));
+        tmp->idx = 7 - i;
+        INIT_LIST_HEAD(tmp, list);
+        assert(list_empty(tmp, list));
+        listp_add(tmp, &list_in_the_sky, list);
+        assert(!list_empty(tmp, list));
+    }
+    assert(!listp_empty(&list_in_the_sky));
+
+    printf("Deletion test 2 starting\n\n");
+    
+    /* Test listp_del_init by migrating to another list */
+    listp_for_each_entry_safe(tmp, n, &list_in_the_sky, list) {
+        listp_del(tmp, &list_in_the_sky, list);
+        listp_add(tmp, &list_in_the_basement, list);
+        //print_list(&list_in_the_sky);
+        //print_list(&list_in_the_basement);
+    }
+
+    //print_list(&list_in_the_sky);
+    //print_list(&list_in_the_basement);
+    assert(listp_empty(&list_in_the_sky));
+    assert_list(&list_in_the_basement, 7, sol5, 0);
+
+    /* Test listp_first_entry, for funzies */
+    assert(listp_first_entry(&list_in_the_basement, simple, list)->idx == 7);
+
+    /*
+    printf("List in the sky:\n");
+    print_list(&list_in_the_sky);
+    printf("\nList in the basement:\n");
+    print_list(&list_in_the_basement);
+    printf("\nfin\n");
+    printf("\nList in the basement, but backward:\n");
+    print_list_reverse(&list_in_the_basement);
+    printf("\nfin\n");
+    printf("\nList in the sky, but backward:\n");
+    print_list_reverse(&list_in_the_sky);
+    printf("\nfin\n");
+    */
+    
+    printf("Deletion test 2 Ending\n\n");
+    
+    /* Test listp_for_each_entry_safe_continue; stop on 4
+     * after deleting 6 and 4, break, and continue. 
+     * */
+    listp_for_each_entry_safe(tmp, n, &list_in_the_basement, list) {
+        if (0 == (tmp->idx % 2)) {
+            int idx = tmp->idx;
+            listp_del(tmp, &list_in_the_basement, list);
+            // NB: The continue pointer needs to be valid (will probably work
+            // by accident even if 4 isn't freed, so better to leak one node
+            if (idx == 4) 
+                break;
+             else
+                free(tmp);
+            
+        }
+    }
+
+    //printf("Continuing\n");
+
+    listp_for_each_entry_safe_continue(tmp, n, &list_in_the_basement, list) {
+        if (0 == (tmp->idx % 2)) {
+            listp_del(tmp, &list_in_the_basement, list);
+            free(tmp);
+        }
+    }
+
+    //print_list(&list_in_the_sky);
+    //print_list(&list_in_the_basement);
+    assert(listp_empty(&list_in_the_sky));
+    assert_list(&list_in_the_basement, 4, sol6, 0);
+
+    /* Test list_splice variants.  Rebuild sky list again */
+    /* Rebuild the list */
+    for (i = 8; i < 14; i++) {
+        tmp = malloc(sizeof(struct simple));
+        tmp->idx = i;
+        INIT_LIST_HEAD(tmp, list);
+        assert(list_empty(tmp, list));
+        listp_add(tmp, &list_in_the_sky, list);
+        assert(!list_empty(tmp, list));
+    }
+    assert(!listp_empty(&list_in_the_sky));
+
+    printf("Begin splice tests \n\n");
+    
+    /* Test listp splice */
+    listp_splice_init(&list_in_the_basement, &list_in_the_sky, list, simple);
+
+    assert(listp_empty(&list_in_the_basement));
+    assert_list(&list_in_the_sky, 10, sol7, 0);
+
+    listp_splice(&list_in_the_sky, &list_in_the_basement, list, simple);
+    INIT_LISTP(&list_in_the_sky);
+
+    assert(listp_empty(&list_in_the_sky));
+    assert_list(&list_in_the_basement, 10, sol7, 0);
+
+    /* Test splicing onto the tail */
+    /* Rebuild the list */
+    for (i = 14; i < 21; i++) {
+        tmp = malloc(sizeof(struct simple));
+        tmp->idx = i;
+        INIT_LIST_HEAD(tmp, list);
+        assert(list_empty(tmp, list));
+        listp_add(tmp, &list_in_the_sky, list);
+        assert(!list_empty(tmp, list));
+    }
+    assert(!listp_empty(&list_in_the_sky));
+
+
+    listp_splice_tail(&list_in_the_sky, &list_in_the_basement, list, simple);
+    INIT_LISTP(&list_in_the_sky);
+
+    /*
+    printf("\nList in the basement:\n");
+    print_list(&list_in_the_basement);
+    printf("\nfin\n");
+
+    printf("\nList in the sky:\n");
+    print_list(&list_in_the_sky);
+    printf("\nfin\n");
+    */
+    
+    
+    printf("Before list move test \n\n");
+
+    /* Test listp_move_tail */
+    listp_for_each_entry_safe(tmp, n, &list_in_the_basement, list) {
+        listp_move_tail(tmp, &list_in_the_sky, &list_in_the_basement, list);
+    }
+
+    assert(listp_empty(&list_in_the_basement));
+    assert_list(&list_in_the_sky, 17, sol8, 0);
+
+    printf("After list move test \n\n");
+
+    /*
+    printf("\nList in the basement:\n");
+    print_list(&list_in_the_basement);
+    printf("\nfin\n");
+
+    printf("\nList in the sky:\n");
+    print_list(&list_in_the_sky);
+    printf("\nfin\n");
+    */
+    
+    printf("All tests passed!\n");
+    return 0;
+}

+ 339 - 0
Pal/lib/list.h

@@ -0,0 +1,339 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+/* Copyright (C) 2017 University of North Carolina at Chapel Hill and
+   Fortanix, Inc.
+   This file is part of Graphene Library OS.
+
+   Graphene Library OS is free software: you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   Graphene Library OS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+ * list.h
+ *
+ * This file defines the list API for the PAL and Library OS.
+ */
+
+#ifndef LIST_H
+#define LIST_H
+
+// Use a new list implementation
+
+/* This list implementation stores a pointer to the next object and casts to
+ * the object, rather than using offsetof().  We try to encapsulate this
+ * change in a macro for declarations, which generates a type declaration for
+ * each list object (giving marginally more help from the compiler
+ * in detecting bugs.
+ * 
+ * In particular, there is a small trade-off in that the association between
+ * list heads and nodes is more explicit and a few more casting errors can be
+ * caught by the compiler, but we add a parameter to some functions (well,
+ * macros) to pass the field of the struct.
+ */
+
+/* How-to:
+ * 
+ * Each list has a pointer (listp) type, and a node (list)type.  We assume
+ * list nodes are embedded in a larger structure; the name of this structure
+ * is used as part of the list type.
+ * 
+ * To define a listp/list pair for a struct foo:
+ * 
+ * DEFINE_LIST(foo);
+ * struct foo {
+ *   int x;
+ *   LIST_TYPE(foo) list; // The list node 
+ * };
+ * 
+ * DEFINE_LISTP(foo);
+ * static LISTP_TYPE(foo) the_list = LISTP_INIT;
+ * 
+ * -----
+ * 
+ * From here, you can use listp_add variants to add an object from the list:
+ * 
+ * struct foo *f = malloc(sizeof(struct foo));
+ * f->x = 1;
+ * INIT_LIST_HEAD(f, list); // The second parameter is the structure member
+ * listp_add(f, &the_list, list);
+ * 
+ * -----
+ * 
+ * There are a number of add variants, some that add in a given position,
+ * others that add to the head or the tail.
+ * 
+ * You can search for an object using a variant of listp_for_each_entry. The
+ * safe variants are safe against deletion.
+ * 
+ * You can remove an object from a list using listp_del.  
+ * 
+ * In this example, we delete everything with a key bigger than 5.
+ * 
+ * LIST_TYPE(foo) *f, *n; // n is not used, just for scratch space
+ * listp_for_each_entry_safe(f, n, &the_list, list) {
+ *    if (f->x > 4) {
+ *         listp_del(f, &the_list, list);
+ *         free(f);
+ *    }
+ * }
+ * 
+ * 
+ * listp_splice moves an entire listp onto another, and list_move_tail takes 
+ * an element off of one list and places it on another.
+ * 
+ * static LISTP_TYPE(foo) other_list; // Assume it is full of goodies
+ *  // Move everything on other_list to the_list
+ * listp_splice_tail(&other_list, &the_list, list, foo); // the third argument
+ *                                                       // is the field; the
+ *                                                       // fourth is the type
+ *                                                       // of the nodes (not 
+ *                                                       // the head pointer).
+ * 
+ * // Use listp_empty to test for emptiness of the list 
+ * assert(listp_empty(&other_ist));
+ * 
+ *  // Now move back anythign less than 6 back to other_list
+ * listp_for_each_entry_safe(f, n, &the_list, list) {
+ *    if (f->x < 6) 
+ *         listp_move_tail(f, &other_list, &the_list, list);
+ * }
+ * 
+ */
+
+// Maybe TODO?
+//
+// Change the order of (node, head, field) -> (head, node, field)
+// drop the listp type to reduce code changes?
+// Cleaner way to express types
+// Add assertion to delete (in debugging mode) that item is on list
+// There are a few places where knowing the listp for deletion is cumbersome;
+//    maybe drop this requirement?
+
+#ifdef DEBUG
+#include <assert.h>
+#define LIST_ASSERT(cond) assert(cond)
+#else
+#define LIST_ASSERT(cond)
+#endif
+
+/* For these macros, do not include the string 'struct' */
+#define LIST_TYPE(STRUCT) struct list_head ##_## STRUCT
+#define LISTP_TYPE(STRUCT) struct listp ##_## STRUCT
+
+/* Declare the enclosing struct for convenience, on 
+ * the assumption that this is primarily used in structure 
+ * definitions, and harmless if duplicated. */
+#define DEFINE_LIST(STRUCT)                     \
+    struct STRUCT;                              \
+    LIST_TYPE(STRUCT) {                         \
+        struct STRUCT *next, *prev;             \
+    }
+
+/* We use LISTP for pointers to a list.  This project only really needs
+ * doubly-linked lists.  We used hlists to get a single pointer for more
+ * efficient hash tables, but they were still effectively doubly-linked
+ * lists. */
+#define DEFINE_LISTP(STRUCT)                    \
+    LISTP_TYPE(STRUCT) {                        \
+        struct STRUCT * first;                  \
+    }
+
+#define LISTP_INIT {NULL}
+
+/* A node not on a list uses NULL; on a list, you 
+ * store self pointers */
+#define INIT_LIST_HEAD(OBJECT, FIELD) do {      \
+        (OBJECT)->FIELD.next = NULL;            \
+        (OBJECT)->FIELD.prev = NULL;            \
+    } while (0)
+
+
+#define INIT_LISTP(OBJECT) do {                 \
+        (OBJECT)->first = NULL;                 \
+    } while (0)
+
+#define listp_empty(HEAD) ((HEAD)->first == NULL)
+
+#define list_empty(NODE, FIELD)                 \
+    ((NODE)->FIELD.next == NULL)
+
+/* This helper takes 3 arguments - all should be containing structures,
+ * and the field to use for the offset to the list node */
+#define __list_add(NEW, NEXT, PREV, FIELD) do {       \
+        typeof(NEW) __tmp_next = (NEXT);              \
+        typeof(NEW) __tmp_prev = (PREV);              \
+        __tmp_prev->FIELD.next = (NEW);               \
+        __tmp_next->FIELD.prev = (NEW);               \
+        (NEW)->FIELD.next = __tmp_next;               \
+        (NEW)->FIELD.prev = __tmp_prev;               \
+    } while (0)
+
+#define list_add(NEW, HEAD, FIELD)                 \
+    __list_add(NEW, (HEAD)->FIELD.next, HEAD, FIELD)
+
+#define listp_add(NEW, HEAD, FIELD) do {                    \
+        if ((HEAD)->first == NULL) {                        \
+            (HEAD)->first = (NEW);                          \
+            (NEW)->FIELD.next = (NEW);                      \
+            (NEW)->FIELD.prev = (NEW);                      \
+        } else {                                            \
+            __list_add(NEW, (HEAD)->first, (HEAD)->first->FIELD.prev, FIELD); \
+            (HEAD)->first = (NEW);                          \
+        }                                                   \
+    } while (0)
+
+/* If NODE is defined, add NEW after NODE; if not, 
+ * put NEW at the front of the list */
+#define listp_add_after(NEW, NODE, HEAD, FIELD) do { \
+        if (NODE)                                \
+            list_add(NEW, NODE, FIELD);          \
+        else                                     \
+            listp_add(NEW, HEAD, FIELD);         \
+    } while(0)
+
+#define list_add_tail(NEW, HEAD, FIELD)                 \
+    __list_add(NEW, HEAD, (HEAD)->FIELD.prev, FIELD)
+
+#define listp_add_tail(NEW, HEAD, FIELD) do {               \
+        if ((HEAD)->first == NULL) {                        \
+            (HEAD)->first = (NEW);                          \
+            (NEW)->FIELD.next = (NEW);                      \
+            (NEW)->FIELD.prev = (NEW);                      \
+        } else                                              \
+            list_add_tail(NEW, (HEAD)->first, FIELD);       \
+    } while (0)
+
+/* Or deletion needs to know the list root */
+#define listp_del(NODE, HEAD, FIELD) do {                               \
+        if ((HEAD)->first == (NODE)) {                                  \
+            if ((NODE)->FIELD.next == NODE) {                           \
+                (HEAD)->first = NULL;                                   \
+            } else {                                                    \
+                (HEAD)->first = (NODE)->FIELD.next;                     \
+            }                                                           \
+        }                                                               \
+        LIST_ASSERT((NODE)->FIELD.prev->FIELD.next == (NODE));          \
+        LIST_ASSERT((NODE)->FIELD.next->FIELD.prev == (NODE));          \
+        (NODE)->FIELD.prev->FIELD.next = (NODE)->FIELD.next;            \
+        (NODE)->FIELD.next->FIELD.prev = (NODE)->FIELD.prev;            \
+    } while(0)
+
+#define listp_del_init(NODE, HEAD, FIELD) do {  \
+        listp_del(NODE, HEAD, FIELD);           \
+        INIT_LIST_HEAD(NODE, FIELD);            \
+    } while(0)
+            
+/* Keep vestigial TYPE and FIELD parameters to minimize disruption
+ * when switching from Linux list implementation */
+#define listp_first_entry(LISTP, TYPE, FIELD) ((LISTP)->first)
+
+/* New API: return last entry in list */
+#define listp_last_entry(LISTP, TYPE, FIELD) ((LISTP)->first->FIELD.prev)
+
+/* Vestigial - for compat with Linux list code; rename to listp?
+ */
+#define list_entry(LISTP, TYPE, FIELD) (LISTP)
+
+#define listp_for_each_entry(CURSOR, HEAD, FIELD)                       \
+    for(int first_iter = ({ (CURSOR) = (HEAD)->first;                   \
+                (HEAD)->first ? 1 : 0; });                              \
+        first_iter || (CURSOR) != (HEAD)->first;                        \
+        (CURSOR) = (CURSOR)->FIELD.next, first_iter = 0)
+
+#define listp_for_each_entry_reverse(CURSOR, HEAD, FIELD)              \
+    for(int first_iter = ({(CURSOR) = ((HEAD)->first                   \
+                    ? (HEAD)->first->FIELD.prev :                      \
+                    (HEAD)->first); (HEAD)->first ? 1 : 0; });         \
+        first_iter || ((CURSOR) && (CURSOR)->FIELD.next != (HEAD)->first); \
+        (CURSOR) = (CURSOR)->FIELD.prev, first_iter = 0)
+
+#define listp_for_each_entry_safe(CURSOR, TMP, HEAD, FIELD)             \
+    for(int first_iter = ({(CURSOR) = (HEAD)->first;                    \
+                    (TMP) = ((CURSOR) ? (CURSOR)->FIELD.next : (CURSOR)); \
+                (HEAD)->first ? 1 : 0; });                              \
+        (first_iter || (CURSOR) != (HEAD)->first) && (HEAD)->first;     \
+        first_iter = (first_iter && (TMP) != (CURSOR) && (HEAD)->first == (TMP) ? \
+                      1: 0),                                            \
+            (CURSOR) = (TMP), (TMP) = (TMP)->FIELD.next)
+
+/* Continue safe iteration with CURSOR->next */
+#define listp_for_each_entry_safe_continue(CURSOR, TMP, HEAD, FIELD)    \
+    for((CURSOR) = (CURSOR)->FIELD.next,                                \
+        (TMP) = (CURSOR)->FIELD.next;                                   \
+        (CURSOR) != (HEAD)->first && (HEAD)->first;                     \
+        (CURSOR) = (TMP), (TMP) = (TMP)->FIELD.next)
+
+/* Assertion code written in Graphene project */
+#define check_list_head(TYPE, head, FIELD)                              \
+        do {                                                            \
+            TYPE pos;                                                   \
+            listp_for_each_entry(pos, head, FIELD) {                    \
+                assert((pos->FIELD.prev != pos && pos->FIELD.next != pos) \
+                       || (pos->FIELD.prev == pos && pos->FIELD.next == pos)); \
+                assert(pos->FIELD.prev->FIELD.next == pos);             \
+                assert(pos->FIELD.next->FIELD.prev == pos);             \
+            }                                                           \
+        } while (0)
+
+// Add NEW to OLD at position first (assuming first is all we need for now)
+// Can probably drop TYPE with some preprocessor smarts
+#define listp_splice(NEW, OLD, FIELD, TYPE) do {                     \
+        if(!listp_empty(NEW)) {                                      \
+            if(listp_empty(OLD)) {                                   \
+                (OLD)->first = (NEW)->first;                         \
+            } else {                                                 \
+                struct TYPE *last_old = (OLD)->first->FIELD.prev;    \
+                (OLD)->first->FIELD.prev->FIELD.next = (NEW)->first;    \
+                (OLD)->first->FIELD.prev = (NEW)->first->FIELD.prev;    \
+                (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first;   \
+                (NEW)->first->FIELD.prev = last_old;                  \
+                (OLD)->first = (NEW)->first;                         \
+            }                                                        \
+        }                                                            \
+    } while (0)
+
+// Add NEW to OLD at last position
+// Can probably drop TYPE with some preprocessor smarts
+#define listp_splice_tail(NEW, OLD, FIELD, TYPE) do {                \
+        if(!listp_empty(NEW)) {                                      \
+            if(listp_empty(OLD)) {                                   \
+                (OLD)->first = (NEW)->first;                         \
+            } else {                                                 \
+                struct TYPE *last_old = (OLD)->first->FIELD.prev;       \
+                last_old->FIELD.next = (NEW)->first;                    \
+                (OLD)->first->FIELD.prev = (NEW)->first->FIELD.prev;    \
+                (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first;    \
+                (NEW)->first->FIELD.prev = last_old;                    \
+            }                                                        \
+        }                                                            \
+    } while (0)
+
+#define listp_splice_init(NEW, OLD, FIELD, TYPE) do {       \
+        listp_splice(NEW, OLD, FIELD, TYPE);                \
+        INIT_LISTP(NEW);                                    \
+    } while(0);
+
+
+#define listp_splice_tail_init(NEW, OLD, FIELD, TYPE) do {  \
+        listp_splice_tail(NEW, OLD, FIELD, TYPE);           \
+        INIT_LISTP(NEW);                                    \
+    } while(0);
+    
+// list_move_tail - delete from OLD, make tail of NEW
+#define listp_move_tail(NODE, NEW, OLD, FIELD) do {   \
+        listp_del_init(NODE, OLD, FIELD);             \
+        listp_add_tail(NODE, NEW, FIELD);             \
+    } while (0)
+
+
+#endif // LIST_H

+ 34 - 30
Pal/lib/memmgr.h

@@ -26,7 +26,7 @@
 #ifndef MEMMGR_H
 #define MEMMGR_H
 
-#include "linux_list.h"
+#include "list.h"
 #include <sys/mman.h>
 
 #ifndef OBJ_TYPE
@@ -46,22 +46,26 @@
 #define system_unlock() ({})
 #endif
 
+DEFINE_LIST(mem_obj);
 typedef struct mem_obj {
     union {
-        struct list_head __list;
+        LIST_TYPE(mem_obj) __list;
         OBJ_TYPE obj;
     };
 } MEM_OBJ_TYPE, * MEM_OBJ;
 
+DEFINE_LIST(mem_area);
 typedef struct mem_area {
-    struct list_head __list;
+    LIST_TYPE(mem_area) __list;
     unsigned int size;
     MEM_OBJ_TYPE objs[];
 } MEM_AREA_TYPE, * MEM_AREA;
 
+DEFINE_LISTP(mem_area);
+DEFINE_LISTP(mem_obj);
 typedef struct mem_mgr {
-    struct list_head area_list;
-    struct list_head free_list;
+    LISTP_TYPE(mem_area) area_list;
+    LISTP_TYPE(mem_obj) free_list;
     MEM_OBJ_TYPE * obj, * obj_top;
 } MEM_MGR_TYPE, * MEM_MGR;
 
@@ -122,11 +126,11 @@ static inline MEM_MGR create_mem_mgr (unsigned int size)
     area = (MEM_AREA) (mem + sizeof(MEM_MGR_TYPE));
     area->size = size;
 
-    INIT_LIST_HEAD(&area->__list);
-    INIT_LIST_HEAD(&mgr->area_list);
-    list_add(&area->__list, &mgr->area_list);
+    INIT_LIST_HEAD(area, __list);
+    INIT_LISTP(&mgr->area_list);
+    listp_add(area, &mgr->area_list, __list);
 
-    INIT_LIST_HEAD(&mgr->free_list);
+    INIT_LISTP(&mgr->free_list);
     __set_free_mem_area(area, mgr, size);
 
     return mgr;
@@ -143,8 +147,8 @@ static inline MEM_MGR enlarge_mem_mgr (MEM_MGR mgr, unsigned int size)
 
     system_lock();
     area->size = size;
-    INIT_LIST_HEAD(&area->__list);
-    list_add(&area->__list, &mgr->area_list);
+    INIT_LIST_HEAD(area, __list);
+    listp_add(area, &mgr->area_list, __list);
     __set_free_mem_area(area, mgr, size);
     system_unlock();
     return mgr;
@@ -154,13 +158,13 @@ static inline void destroy_mem_mgr (MEM_MGR mgr)
 {
     MEM_AREA tmp, n, first = NULL;
 
-    first = tmp = list_first_entry(&mgr->area_list, MEM_AREA_TYPE, __list);
+    first = tmp = listp_first_entry(&mgr->area_list, MEM_AREA_TYPE, __list);
 
     if (!first)
         return;
 
-    list_for_each_entry_safe_continue(tmp, n, &mgr->area_list, __list) {
-        list_del(&tmp->__list);
+    listp_for_each_entry_safe_continue(tmp, n, &mgr->area_list, __list) {
+        listp_del(tmp, &mgr->area_list, __list);
         system_free(tmp, sizeof(MEM_AREA_TYPE) + __SUM_OBJ_SIZE(tmp->size));
     }
 
@@ -172,15 +176,15 @@ static inline OBJ_TYPE * get_mem_obj_from_mgr (MEM_MGR mgr)
     MEM_OBJ mobj;
 
     system_lock();
-    if (mgr->obj == mgr->obj_top && list_empty(&mgr->free_list)) {
+    if (mgr->obj == mgr->obj_top && listp_empty(&mgr->free_list)) {
         system_unlock();
         return NULL;
     }
 
-    if (!list_empty(&mgr->free_list)) {
-        mobj = list_first_entry(&mgr->free_list, MEM_OBJ_TYPE, __list);
-        list_del_init(&mobj->__list);
-        check_list_head(&mgr->free_list);
+    if (!listp_empty(&mgr->free_list)) {
+        mobj = listp_first_entry(&mgr->free_list, MEM_OBJ_TYPE, __list);
+        listp_del_init(mobj, &mgr->free_list, __list);
+        check_list_head(MEM_OBJ, &mgr->free_list, __list);
     } else {
         mobj = mgr->obj++;
     }
@@ -194,7 +198,7 @@ static inline OBJ_TYPE * get_mem_obj_from_mgr_enlarge (MEM_MGR mgr,
     MEM_OBJ mobj;
 
     system_lock();
-    if (mgr->obj == mgr->obj_top && list_empty(&mgr->free_list)) {
+    if (mgr->obj == mgr->obj_top && listp_empty(&mgr->free_list)) {
         system_unlock();
 
         if (!size)
@@ -208,15 +212,15 @@ static inline OBJ_TYPE * get_mem_obj_from_mgr_enlarge (MEM_MGR mgr,
 
         system_lock();
         area->size = size;
-        INIT_LIST_HEAD(&area->__list);
-        list_add(&area->__list, &mgr->area_list);
+        INIT_LIST_HEAD(area, __list);
+        listp_add(area, &mgr->area_list, __list);
         __set_free_mem_area(area, mgr, size);
     }
 
-    if (!list_empty(&mgr->free_list)) {
-        mobj = list_first_entry(&mgr->free_list, MEM_OBJ_TYPE, __list);
-        list_del_init(&mobj->__list);
-        check_list_head(&mgr->free_list);
+    if (!listp_empty(&mgr->free_list)) {
+        mobj = listp_first_entry(&mgr->free_list, MEM_OBJ_TYPE, __list);
+        listp_del_init(mobj, &mgr->free_list, __list);
+        check_list_head(MEM_OBJ, &mgr->free_list, __list);
     } else {
         mobj = mgr->obj++;
     }
@@ -230,16 +234,16 @@ static inline void free_mem_obj_to_mgr (MEM_MGR mgr, OBJ_TYPE * obj)
 
     system_lock();
     MEM_AREA area, found = NULL;
-    list_for_each_entry(area, &mgr->area_list, __list)
+    listp_for_each_entry(area, &mgr->area_list, __list)
         if (mobj >= area->objs && mobj < area->objs + area->size) {
             found = area;
             break;
         }
 
     if (found) {
-        INIT_LIST_HEAD(&mobj->__list);
-        list_add_tail(&mobj->__list, &mgr->free_list);
-        check_list_head(&mgr->free_list);
+        INIT_LIST_HEAD(mobj, __list);
+        listp_add_tail(mobj, &mgr->free_list, __list);
+        check_list_head(MEM_OBJ, &mgr->free_list, __list);
     }
 
     system_unlock();

+ 0 - 1
Pal/lib/pal_crypto.h

@@ -1,5 +1,4 @@
 /* Copyright (C) 2014 OSCAR lab, Stony Brook University
-   Copyright (C) 2017 Fortanix, Inc.
 
    This file is part of Graphene Library OS.
 

+ 28 - 19
Pal/lib/slabmgr.h

@@ -26,7 +26,7 @@
 #ifndef SLABMGR_H
 #define SLABMGR_H
 
-#include "linux_list.h"
+#include "list.h"
 #include <assert.h>
 #include <sys/mman.h>
 
@@ -68,11 +68,13 @@
  */
 #define ROUND_UP(_x, _y) ((((_x) + (_y) - 1) / (_y)) * (_y))
 
+DEFINE_LIST(slab_obj);
+
 typedef struct __attribute__((packed)) slab_obj {
     unsigned char level;
     unsigned char padding[OBJ_PADDING];
     union {
-        struct list_head __list;
+        LIST_TYPE(slab_obj) __list;
         unsigned char *raw;
     };
 } SLAB_OBJ_TYPE, * SLAB_OBJ;
@@ -82,8 +84,9 @@ typedef struct __attribute__((packed)) slab_obj {
  * invariant is respected. */
 #define AREA_PADDING 12
 
+DEFINE_LIST(slab_area);
 typedef struct __attribute__((packed)) slab_area {
-    struct list_head __list;
+    LIST_TYPE(slab_area) __list;
     unsigned int size;
     unsigned char pad[AREA_PADDING];
     unsigned char raw[];
@@ -110,7 +113,7 @@ struct slab_debug {
 #endif
 
 #define SLAB_HDR_SIZE \
-    ROUND_UP((sizeof(SLAB_OBJ_TYPE) - sizeof(struct list_head) +    \
+    ROUND_UP((sizeof(SLAB_OBJ_TYPE) - sizeof(LIST_TYPE(slab_obj)) +     \
               SLAB_DEBUG_SIZE + SLAB_CANARY_SIZE), \
              MIN_MALLOC_ALIGNMENT)
 
@@ -134,9 +137,11 @@ struct slab_debug {
 
 static int slab_levels[SLAB_LEVEL] = { SLAB_LEVEL_SIZES };
 
+DEFINE_LISTP(slab_obj);
+DEFINE_LISTP(slab_area);
 typedef struct slab_mgr {
-    struct list_head area_list[SLAB_LEVEL];
-    struct list_head free_list[SLAB_LEVEL];
+    LISTP_TYPE(slab_area) area_list[SLAB_LEVEL];
+    LISTP_TYPE(slab_obj) free_list[SLAB_LEVEL];
     unsigned int size[SLAB_LEVEL];
     void * addr[SLAB_LEVEL], * addr_top[SLAB_LEVEL];
 } SLAB_MGR_TYPE, * SLAB_MGR;
@@ -155,6 +160,10 @@ typedef struct __attribute__((packed)) large_mem_obj {
 #define OBJ_LEVEL(obj) ((obj)->level)
 #define OBJ_RAW(obj) (&(obj)->raw)
 
+#ifndef container_of
+#define container_of(ptr, type, field) ((type *)((char *)(ptr) - offsetof(type, field)))
+#endif
+
 #define RAW_TO_LEVEL(raw_ptr) \
             (*((unsigned char *) (raw_ptr) - OBJ_PADDING - 1))
 #define RAW_TO_OBJ(raw_ptr, type) container_of((raw_ptr), type, raw)
@@ -243,11 +252,11 @@ static inline SLAB_MGR create_slab_mgr (void)
         area = (SLAB_AREA) addr;
         area->size = STARTUP_SIZE;
 
-        INIT_LIST_HEAD(&area->__list);
-        INIT_LIST_HEAD(&mgr->area_list[i]);
-        list_add_tail(&area->__list, &mgr->area_list[i]);
+        INIT_LIST_HEAD(area, __list);
+        INIT_LISTP(&mgr->area_list[i]);
+        listp_add_tail(area, &mgr->area_list[i], __list);
 
-        INIT_LIST_HEAD(&mgr->free_list[i]);
+        INIT_LISTP(&mgr->free_list[i]);
         mgr->size[i] = 0;
         __set_free_slab_area(area, mgr, i);
 
@@ -265,7 +274,7 @@ static inline void destroy_slab_mgr (SLAB_MGR mgr)
     for (i = 0 ; i < SLAB_LEVEL; i++) {
         area = (SLAB_AREA) addr;
 
-        list_for_each_entry_safe(tmp, n, &mgr->area_list[i], __list) {
+        listp_for_each_entry_safe(tmp, n, &mgr->area_list[i], __list) {
             if (tmp != area)
                 system_free(area,
                             __MAX_MEM_SIZE(slab_levels[i], area->size));
@@ -294,8 +303,8 @@ static inline SLAB_MGR enlarge_slab_mgr (SLAB_MGR mgr, int level)
 
     system_lock();
     area->size = size;
-    INIT_LIST_HEAD(&area->__list);
-    list_add(&area->__list, &mgr->area_list[level]);
+    INIT_LIST_HEAD(area, __list);
+    listp_add(area, &mgr->area_list[level], __list);
     __set_free_slab_area(area, mgr, level);
     system_unlock();
 
@@ -329,15 +338,15 @@ static inline void * slab_alloc (SLAB_MGR mgr, int size)
 
     system_lock();
     if (mgr->addr[level] == mgr->addr_top[level] &&
-        list_empty(&mgr->free_list[level])) {
+        listp_empty(&mgr->free_list[level])) {
         system_unlock();
         enlarge_slab_mgr(mgr, level);
         system_lock();
     }
 
-    if (!list_empty(&mgr->free_list[level])) {
-        mobj = list_first_entry(&mgr->free_list[level], SLAB_OBJ_TYPE, __list);
-        list_del(&mobj->__list);
+    if (!listp_empty(&mgr->free_list[level])) {
+        mobj = listp_first_entry(&mgr->free_list[level], SLAB_OBJ_TYPE, __list);
+        listp_del(mobj, &mgr->free_list[level], __list);
     } else {
         mobj = (void *) mgr->addr[level];
         mgr->addr[level] += slab_levels[level] + SLAB_HDR_SIZE;
@@ -416,8 +425,8 @@ static inline void slab_free (SLAB_MGR mgr, void * obj)
     SLAB_OBJ mobj = RAW_TO_OBJ(obj, SLAB_OBJ_TYPE);
 
     system_lock();
-    INIT_LIST_HEAD(&mobj->__list);
-    list_add_tail(&mobj->__list, &mgr->free_list[level]);
+    INIT_LIST_HEAD(mobj, __list);
+    listp_add_tail(mobj, &mgr->free_list[level], __list);
     system_unlock();
 }
 

+ 2 - 1
Pal/src/db_exception.c

@@ -29,7 +29,8 @@
 #include "pal_internal.h"
 #include "pal_error.h"
 #include "api.h"
-#include "linux_list.h"
+#include "list.h"
+#include "pal_debug.h"
 
 #define INIT_EVENT_HANDLER      { .lock = LOCK_INIT }
 

+ 1 - 1
Pal/src/host/FreeBSD/db_exception.c

@@ -32,7 +32,7 @@
 #include "pal_error.h"
 #include "pal_security.h"
 #include "api.h"
-#include "linux_list.h"
+#include "list.h"
 
 #include <atomic.h>
 #include <sigset.h>

+ 9 - 7
Pal/src/host/Linux-SGX/db_process.c

@@ -45,13 +45,15 @@
 typedef __kernel_pid_t pid_t;
 #include <asm/fcntl.h>
 
+DEFINE_LIST(trusted_child);
 struct trusted_child {
-    struct list_head list;
+    LIST_TYPE(trusted_child) list;
     sgx_arch_hash_t mrenclave;
     char uri[];
 };
 
-static LIST_HEAD(trusted_children);
+DEFINE_LISTP(trusted_child);
+static LISTP_TYPE(trusted_child) trusted_children = LISTP_INIT;
 static struct spinlock trusted_children_lock = LOCK_INIT;
 
 int register_trusted_child(const char * uri, const char * mrenclave_str)
@@ -61,7 +63,7 @@ int register_trusted_child(const char * uri, const char * mrenclave_str)
 
     _DkSpinLock(&trusted_children_lock);
 
-    list_for_each_entry(tc, &trusted_children, list) {
+    listp_for_each_entry(tc, &trusted_children, list) {
         if (!memcmp(tc->uri, uri, uri_len + 1)) {
             _DkSpinUnlock(&trusted_children_lock);
             return 0;
@@ -73,7 +75,7 @@ int register_trusted_child(const char * uri, const char * mrenclave_str)
     if (!new)
         return -PAL_ERROR_NOMEM;
 
-    INIT_LIST_HEAD(&new->list);
+    INIT_LIST_HEAD(new, list);
     memcpy(new->uri, uri, uri_len + 1);
 
     char mrenclave_text[sizeof(sgx_arch_hash_t) * 2 + 1] = "\0";
@@ -118,7 +120,7 @@ int register_trusted_child(const char * uri, const char * mrenclave_str)
 
     _DkSpinLock(&trusted_children_lock);
 
-    list_for_each_entry(tc, &trusted_children, list) {
+    listp_for_each_entry(tc, &trusted_children, list) {
         if (!memcmp(tc->uri, uri, uri_len + 1)) {
             _DkSpinUnlock(&trusted_children_lock);
             free(new);
@@ -126,7 +128,7 @@ int register_trusted_child(const char * uri, const char * mrenclave_str)
         }
     }
 
-    list_add_tail(&new->list, &trusted_children);
+    listp_add_tail(new, &trusted_children, list);
     _DkSpinUnlock(&trusted_children_lock);
     return 0;
 }
@@ -175,7 +177,7 @@ static int check_child_mrenclave (sgx_arch_hash_t * mrenclave,
     struct trusted_child * tc;
     _DkSpinLock(&trusted_children_lock);
 
-    list_for_each_entry(tc, &trusted_children, list) {
+    listp_for_each_entry(tc, &trusted_children, list) {
         if (!memcmp(mrenclave, tc->mrenclave, sizeof(sgx_arch_hash_t))) {
             _DkSpinUnlock(&trusted_children_lock);
             SGX_DBG(DBG_S, "trusted child: %s\n", tc->uri);

+ 11 - 10
Pal/src/host/Linux-SGX/db_threading.c

@@ -39,10 +39,11 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-#include <linux_list.h>
+#include <list.h>
 
 static PAL_LOCK thread_list_lock = LOCK_INIT;
-static LIST_HEAD(thread_list);
+DEFINE_LISTP(pal_handle_thread);
+static LISTP_TYPE(pal_handle_thread) thread_list = LISTP_INIT;
 
 struct thread_param {
     int (*callback) (void *);
@@ -53,13 +54,13 @@ extern void * enclave_base;
 
 void pal_start_thread (void)
 {
-    PAL_HANDLE new_thread = NULL, tmp;
+    struct pal_handle_thread *new_thread = NULL, *tmp;
 
     _DkInternalLock(&thread_list_lock);
-    list_for_each_entry(tmp, &thread_list, thread.list)
-        if (!tmp->thread.tcs) {
+    listp_for_each_entry(tmp, &thread_list, list)
+        if (!tmp->tcs) {
             new_thread = tmp;
-            new_thread->thread.tcs =
+            new_thread->tcs =
                 enclave_base + GET_ENCLAVE_TLS(tcs_offset);
             break;
         }
@@ -69,11 +70,11 @@ void pal_start_thread (void)
         return;
 
     struct thread_param * thread_param =
-            (struct thread_param *) new_thread->thread.param;
+            (struct thread_param *) new_thread->param;
     int (*callback) (void *) = thread_param->callback;
     const void * param = thread_param->param;
     free(thread_param);
-    new_thread->thread.param = NULL;
+    new_thread->param = NULL;
     SET_ENCLAVE_TLS(thread, new_thread);
     callback((void *) param);
 }
@@ -87,14 +88,14 @@ int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
     PAL_HANDLE new_thread = malloc(HANDLE_SIZE(thread));
     SET_HANDLE_TYPE(new_thread, thread);
     new_thread->thread.tcs = NULL;
-    INIT_LIST_HEAD(&new_thread->thread.list);
+    INIT_LIST_HEAD(&new_thread->thread, list);
     struct thread_param * thread_param = malloc(sizeof(struct thread_param));
     thread_param->callback = callback;
     thread_param->param = param;
     new_thread->thread.param = (void *) thread_param;
 
     _DkInternalLock(&thread_list_lock);
-    list_add_tail(&new_thread->thread.list, &thread_list);
+    listp_add_tail(&new_thread->thread, &thread_list, list);
     _DkInternalUnlock(&thread_list_lock);
 
     int ret = ocall_wake_thread(NULL);

+ 16 - 14
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -7,7 +7,7 @@
 #include <pal_security.h>
 #include <pal_crypto.h>
 #include <api.h>
-#include <linux_list.h>
+#include <list.h>
 
 #include "enclave_pages.h"
 
@@ -105,17 +105,19 @@ int init_enclave_key (void)
     return 0;
 }
 
+DEFINE_LIST(trusted_file);
 struct trusted_file {
-    struct list_head list;
-    int64_t         index;
-    uint64_t        size;
-    int             uri_len;
-    char            uri[URI_MAX];
-    sgx_checksum_t  checksum;
-    sgx_stub_t *    stubs;
+    LIST_TYPE(trusted_file) list;
+    int64_t index;
+    uint64_t size;
+    int uri_len;
+    char uri[URI_MAX];
+    sgx_checksum_t checksum;
+    sgx_stub_t * stubs;
 };
 
-static LIST_HEAD(trusted_file_list);
+DEFINE_LISTP(trusted_file);
+static LISTP_TYPE(trusted_file) trusted_file_list = LISTP_INIT;
 static struct spinlock trusted_file_lock = LOCK_INIT;
 static int trusted_file_indexes = 0;
 
@@ -149,7 +151,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
 
     _DkSpinLock(&trusted_file_lock);
 
-    list_for_each_entry(tmp, &trusted_file_list, list) {
+    listp_for_each_entry(tmp, &trusted_file_list, list) {
         if (tmp->stubs) {
             /* trusted files: must be exactly the same URI */
             if (tmp->uri_len == uri_len && !memcmp(tmp->uri, normpath, uri_len + 1)) {
@@ -312,7 +314,7 @@ static int register_trusted_file (const char * uri, const char * checksum_str)
 
     _DkSpinLock(&trusted_file_lock);
 
-    list_for_each_entry(tf, &trusted_file_list, list) {
+    listp_for_each_entry(tf, &trusted_file_list, list) {
         if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
             _DkSpinUnlock(&trusted_file_lock);
             return 0;
@@ -324,7 +326,7 @@ static int register_trusted_file (const char * uri, const char * checksum_str)
     if (!new)
         return -PAL_ERROR_NOMEM;
 
-    INIT_LIST_HEAD(&new->list);
+    INIT_LIST_HEAD(new, list);
     new->uri_len = uri_len;
     memcpy(new->uri, uri, uri_len + 1);
     new->size = 0;
@@ -385,7 +387,7 @@ static int register_trusted_file (const char * uri, const char * checksum_str)
 
     _DkSpinLock(&trusted_file_lock);
 
-    list_for_each_entry(tf, &trusted_file_list, list) {
+    listp_for_each_entry(tf, &trusted_file_list, list) {
         if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
             _DkSpinUnlock(&trusted_file_lock);
             free(new);
@@ -393,7 +395,7 @@ static int register_trusted_file (const char * uri, const char * checksum_str)
         }
     }
 
-    list_add_tail(&new->list, &trusted_file_list);
+    listp_add_tail(new, &trusted_file_list, list);
     _DkSpinUnlock(&trusted_file_lock);
     return 0;
 }

+ 45 - 25
Pal/src/host/Linux-SGX/enclave_pages.c

@@ -7,19 +7,23 @@
 #include <api.h>
 #include "enclave_pages.h"
 
-#include <linux_list.h>
+#include <list.h>
 
 static unsigned long pgsz = PRESET_PAGESIZE;
 void * heap_base;
 static uint64_t heap_size;
 
+/* This list keeps heap_vma structures of free regions
+ * organized in DESCENDING order.*/
+DEFINE_LIST(heap_vma);
 struct heap_vma {
-    struct list_head list;
+    LIST_TYPE(heap_vma) list;
     void * top;
     void * bottom;
 };
 
-static LIST_HEAD(heap_vma_list);
+DEFINE_LISTP(heap_vma);
+static LISTP_TYPE(heap_vma) heap_vma_list = LISTP_INIT;
 PAL_LOCK heap_vma_lock = LOCK_INIT;
 
 struct atomic_int alloced_pages, max_alloced_pages;
@@ -36,8 +40,8 @@ void init_pages (void)
         struct heap_vma * vma = malloc(sizeof(struct heap_vma));
         vma->top = pal_sec.exec_addr + pal_sec.exec_size;
         vma->bottom = pal_sec.exec_addr;
-        INIT_LIST_HEAD(&vma->list);
-        list_add(&vma->list, &heap_vma_list);
+        INIT_LIST_HEAD(vma, list);
+        listp_add(vma, &heap_vma_list, list);
     }
 }
 
@@ -49,7 +53,7 @@ static void assert_vma_list (void)
     void * last_addr = heap_base + heap_size;
     struct heap_vma * vma;
 
-    list_for_each_entry(vma, &heap_vma_list, list) {
+    listp_for_each_entry(vma, &heap_vma_list, list) {
         SGX_DBG(DBG_M, "[%d] %p - %p\n", pal_sec.pid, vma->bottom, vma->top);
         if (last_addr < vma->top || vma->top <= vma->bottom) {
             SGX_DBG(DBG_E, "*** [%d] corrupted heap vma: %p - %p (last = %p) ***\n", pal_sec.pid, vma->bottom, vma->top, last_addr);
@@ -87,9 +91,15 @@ void * get_reserved_pages(void * addr, uint64_t size)
     struct heap_vma * prev = NULL, * next;
     struct heap_vma * vma;
 
+    /* Allocating in the heap region.  This loop searches the vma list to
+     * find the first vma with a starting address lower than the requested
+     * address.  Recall that vmas are in descending order.  
+     * 
+     * If the very first vma matches, prev will be null.  
+     */
     if (addr && addr >= heap_base &&
         addr + size <= heap_base + heap_size) {
-        list_for_each_entry(vma, &heap_vma_list, list) {
+        listp_for_each_entry(vma, &heap_vma_list, list) {
             if (vma->bottom < addr)
                 break;
             prev = vma;
@@ -104,10 +114,8 @@ void * get_reserved_pages(void * addr, uint64_t size)
 
     void * avail_top = heap_base + heap_size;
 
-    list_for_each_entry(vma, &heap_vma_list, list) {
-        if (vma->top < heap_base)
-            break;
-        if (avail_top >= vma->top + size) {
+    listp_for_each_entry(vma, &heap_vma_list, list) {
+        if (avail_top - vma->top > size) {
             addr = avail_top - size;
             goto allocated;
         }
@@ -128,11 +136,21 @@ void * get_reserved_pages(void * addr, uint64_t size)
 
 allocated:
     if (prev) {
-        next = (prev->list.next == &heap_vma_list) ? NULL :
-               list_entry(prev->list.next, struct heap_vma, list);
+        // If this is the last entry, don't wrap around
+        if (prev->list.next == listp_first_entry(&heap_vma_list, struct heap_vma, list))
+            next = NULL;
+        else 
+            next = prev->list.next;
     } else {
-        next = list_empty(&heap_vma_list) ? NULL :
-               list_first_entry(&heap_vma_list, struct heap_vma, list);
+        /* In this case, the list is empty, or 
+         * first vma starts at or below the allocation site.
+         * 
+         * The next field will be used to merge vmas with the allocation, if 
+         * they overlap, until the vmas drop below the requested addr
+         * (traversing in decreasing virtual address order)
+         */
+        next = listp_empty(&heap_vma_list) ? NULL :
+            listp_first_entry(&heap_vma_list, struct heap_vma, list);
     }
 
     if (prev && next)
@@ -150,7 +168,9 @@ allocated:
         if (prev->bottom > addr + size)
             break;
 
-        if (prev->list.prev != &heap_vma_list)
+        /* This appears to be doing a reverse search; we should stop before we
+         * wrap back to the last entry */
+        if (prev->list.prev != listp_last_entry(&heap_vma_list, struct heap_vma, list))
             prev_prev = list_entry(prev->list.prev, struct heap_vma, list);
 
         if (!vma) {
@@ -165,7 +185,7 @@ allocated:
                     prev->bottom, prev->top);
 
             vma->top = (prev->top > vma->top) ? prev->top : vma->top;
-            list_del(&prev->list);
+            listp_del(prev, &heap_vma_list,list);
             free(prev);
         }
 
@@ -178,7 +198,7 @@ allocated:
         if (next->top < addr)
             break;
 
-        if (next->list.next != &heap_vma_list)
+        if (next->list.next != listp_first_entry(&heap_vma_list, struct heap_vma, list))
             next_next = list_entry(next->list.next, struct heap_vma, list);
 
         if (!vma) {
@@ -192,7 +212,7 @@ allocated:
                     next->bottom, next->top);
 
             vma->bottom = next->bottom;
-            list_del(&next->list);
+            listp_del(next, &heap_vma_list, list);
             free(next);
         }
 
@@ -203,8 +223,8 @@ allocated:
         vma = malloc(sizeof(struct heap_vma));
         vma->top = addr + size;
         vma->bottom = addr;
-        INIT_LIST_HEAD(&vma->list);
-        list_add(&vma->list, prev ? &prev->list : &heap_vma_list);
+        INIT_LIST_HEAD(vma, list);
+        listp_add_after(vma, prev, &heap_vma_list, list);
     }
 
     if (vma->bottom >= vma->top) {
@@ -251,7 +271,7 @@ void free_pages(void * addr, uint64_t size)
 
     struct heap_vma * vma, * p;
 
-    list_for_each_entry_safe(vma, p, &heap_vma_list, list) {
+    listp_for_each_entry_safe(vma, p, &heap_vma_list, list) {
         if (vma->bottom >= addr_top)
             continue;
         if (vma->top <= addr)
@@ -260,13 +280,13 @@ void free_pages(void * addr, uint64_t size)
             struct heap_vma * new = malloc(sizeof(struct heap_vma));
             new->top = addr;
             new->bottom = vma->bottom;
-            INIT_LIST_HEAD(&new->list);
-            list_add(&new->list, &vma->list);
+            INIT_LIST_HEAD(new, list);
+            list_add(new, vma, list);
         }
 
         vma->bottom = addr_top;
         if (vma->top <= vma->bottom) {
-            list_del(&vma->list); free(vma);
+            listp_del(vma, &heap_vma_list, list); free(vma);
         }
     }
 

+ 1 - 1
Pal/src/host/Linux-SGX/enclave_untrusted.c

@@ -20,8 +20,8 @@
 #include <pal_internal.h>
 #include <pal_security.h>
 #include <pal_error.h>
-#include <linux_list.h>
 #include <api.h>
+#include <assert.h>
 
 #include "enclave_ocalls.h"
 

+ 11 - 7
Pal/src/host/Linux-SGX/pal_host.h

@@ -47,7 +47,7 @@ int _DkSpinUnlock (struct spinlock * lock);
 void * malloc_untrusted (int size);
 void free_untrusted (void * mem);
 
-#include <linux_list.h>
+#include <list.h>
 
 /* internal Mutex design, the structure has to align at integer boundary
    because it is required by futex call. If DEBUG_MUTEX is defined,
@@ -66,6 +66,15 @@ struct mutex_handle {
 #define MUTEX_HANDLE_INIT    { .u = 0 }
 #define INIT_MUTEX_HANDLE(m)  do { m->u = 0; } while (0)
 
+DEFINE_LIST(pal_handle_thread);
+struct pal_handle_thread {
+    PAL_HDR reserved;
+    PAL_IDX tid;
+    PAL_PTR tcs;
+    LIST_TYPE(pal_handle_thread) list;
+    void * param;
+};
+
 typedef union pal_handle
 {
     /* TSAI: Here we define the internal types of PAL_HANDLE
@@ -159,12 +168,7 @@ typedef union pal_handle
         PAL_BOL nonblocking;
     } mcast;
 
-    struct {
-        PAL_HDR reserved;
-        PAL_PTR tcs;
-        struct list_head list;
-        void * param;
-    } thread;
+    struct pal_handle_thread thread;
 
     struct {
         PAL_HDR reserved;

+ 0 - 1
Pal/src/host/Linux-SGX/sgx_graphene.c

@@ -19,7 +19,6 @@
 
 #include <pal.h>
 #include <pal_error.h>
-#include <linux_list.h>
 #include <atomic.h>
 
 #include <linux/futex.h>

+ 1 - 18
Pal/src/pal_debug.h

@@ -27,24 +27,7 @@
 #define PAL_DEBUG_H
 
 #include "pal.h"
-
-#ifdef IN_PAL
-
-#ifndef assert
-void __assert (void);
-
-#define assert(val)                                                      \
-    do {                                                                 \
-        if (!(val)) {                                                    \
-            printf("Assertion failed (%s): %s: %d\n", #val,              \
-                   __FILE__, __LINE__);                                  \
-            __assert();                                                  \
-            _DkProcessExit(1);                                           \
-        }                                                                \
-    } while (0)
-#endif
-
-#endif /* IN_PAL */
+#include <assert.h>
 
 int pal_printf (const char *fmt, ...);
 

+ 0 - 1
Pal/src/slab.c

@@ -31,7 +31,6 @@
 #include "pal_defs.h"
 #include "pal_error.h"
 #include "pal_debug.h"
-#include "linux_list.h"
 
 static int slab_alignment;
 static PAL_LOCK slab_mgr_lock = LOCK_INIT;