imcplugin demo: Extend to support stat() call
[nativeclient.git] / service_runtime / nacl_sync_queue.c
blobc29cb45b958b33e4cffe67b33913f1dcaf17a8cb
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl service runtime synchronized queue.
36 #include "native_client/service_runtime/nacl_sync_queue.h"
38 #include "native_client/service_runtime/nacl_check.h"
39 #include "native_client/service_runtime/nacl_log.h"
40 #include "native_client/service_runtime/nacl_sync_checked.h"
42 struct NaClSyncQueueItem {
43 struct NaClSyncQueueItem *next;
44 void *item; /* arbitrary object */
47 int NaClSyncQueueEmptyMu(struct NaClSyncQueue *nsqp)
49 return NULL == nsqp->head;
52 int NaClSyncQueueEmpty(struct NaClSyncQueue *nsqp)
54 int empty;
56 NaClXMutexLock(&nsqp->mu);
57 empty = NaClSyncQueueEmptyMu(nsqp);
58 NaClXMutexUnlock(&nsqp->mu);
59 return empty;
62 int NaClSyncQueueCtor(struct NaClSyncQueue *nsqp)
64 if (!NaClMutexCtor(&nsqp->mu)) {
65 return 0;
67 if (!NaClCondVarCtor(&nsqp->cv)) {
68 NaClMutexDtor(&nsqp->mu);
69 return 0;
71 nsqp->head = NULL;
72 nsqp->insert_pt = &nsqp->head;
73 nsqp->quit = 0;
75 /* post-condition: NaClSyncQueueEmpty(nsqp) != 0 */
76 return 1;
79 void NaClSyncQueueDtor(struct NaClSyncQueue *nsqp)
82 * NB: sanity check is not complete, since after dropping the lock
83 * and prior to deallocating the mutex, another (confused) thread
84 * could come along and insert an object. Since such a confused
85 * thread might try to insert an object into the queue even after
86 * the mutex and condvar is dtor'd, we're pretty much stuck.
88 CHECK(NaClSyncQueueEmpty(nsqp));
89 NaClMutexDtor(&nsqp->mu);
90 NaClCondVarDtor(&nsqp->cv);
93 void NaClSyncQueueInsert(struct NaClSyncQueue *nsqp,
94 void *item)
96 struct NaClSyncQueueItem *nsqip;
98 NaClLog(3, "NaClSyncQueueInsert(0x%08"PRIxPTR",0x%08"PRIxPTR")\n",
99 (uintptr_t) nsqp,
100 (uintptr_t) item);
102 nsqip = malloc(sizeof *nsqip);
103 if (NULL == nsqip) {
104 NaClLog(LOG_FATAL, "Out of memory for NaClSyncQueue item\n");
106 nsqip->next = NULL;
107 nsqip->item = item;
108 NaClXMutexLock(&nsqp->mu);
109 *nsqp->insert_pt = nsqip;
110 nsqp->insert_pt = &nsqip->next;
111 NaClXCondVarSignal(&nsqp->cv); /* non-empty or quit*/
112 NaClXMutexUnlock(&nsqp->mu);
116 void NaClSyncQueueQuit(struct NaClSyncQueue *nsqp)
118 NaClXMutexLock(&nsqp->mu);
119 nsqp->quit = 1;
120 NaClXCondVarSignal(&nsqp->cv);
121 NaClXMutexUnlock(&nsqp->mu);
124 void *NaClSyncQueueDequeue(struct NaClSyncQueue *nsqp)
126 struct NaClSyncQueueItem *qitem;
127 void *item;
129 NaClLog(3, "NaClSyncQueueDequeue: waiting on queue 0x%08"PRIxPTR"\n",
130 (uintptr_t) nsqp);
131 NaClXMutexLock(&nsqp->mu);
132 while (NaClSyncQueueEmptyMu(nsqp) && !nsqp->quit) {
133 NaClLog(3, "NaClSyncQueueDequeue: waiting\n");
134 NaClCondVarWait(&nsqp->cv, &nsqp->mu);
137 if (nsqp->quit) {
138 item = NULL;
139 } else {
140 CHECK(!NaClSyncQueueEmptyMu(nsqp));
142 qitem = nsqp->head;
143 nsqp->head = qitem->next;
144 if (NULL == nsqp->head) {
145 nsqp->insert_pt = &nsqp->head;
147 item = qitem->item;
148 free(qitem);
151 NaClXMutexUnlock(&nsqp->mu);
153 NaClLog(3, "NaClSyncQueueDequeue: returning item 0x%08"PRIxPTR"\n",
154 (uintptr_t) item);
155 return item;