3 * \brief Semaphore API Implementation
7 * Copyright (c) 2011, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
15 #include <barrelfish/barrelfish.h>
17 #include <octopus/init.h>
18 #include <octopus/getset.h>
19 #include <octopus/trigger.h>
20 #include <octopus/lock.h>
21 #include <octopus/semaphores.h>
25 static uint32_t get_next_id(void)
28 char* lock_record = NULL;
31 // Find a valid ID for our next semaphore
33 // This lock makes sure that we don't
34 // have concurrent access to sem.ids
35 errval_t err = oct_lock("sem.lock", &lock_record);
36 assert(err_is_ok(err));
38 err = oct_get(&record, "sem.ids { current_id: _ }");
40 err = oct_read(record, "_ { current_id: %d }", &id);
41 assert(err_is_ok(err));
43 else if (err_no(err) == OCT_ERR_NO_RECORD) {
44 err = oct_set("sem.ids { current_id: 0 }");
45 assert(err_is_ok(err));
48 assert(!"Should not happen.");
53 err = oct_set("sem.ids { current_id: %lu }", id);
54 assert(err_is_ok(err));
56 err = oct_unlock(lock_record);
59 assert(err_is_ok(err));
64 errval_t oct_sem_new(uint32_t* id, size_t value)
66 // Find a valid ID for our next semaphore
68 //debug_printf("oct_sem_new id is: %d\n", *id);
70 errval_t err = SYS_ERR_OK;
71 for (size_t i=0; i < value; i++) {
72 err = oct_sem_post(*id);
73 if (err_is_fail(err)) {
81 errval_t oct_sem_post(uint32_t id)
83 return oct_mset(SET_SEQUENTIAL, "sem.%d. { sem: %d }", id, id);
86 errval_t oct_sem_wait(uint32_t id)
88 errval_t err = SYS_ERR_OK;
90 octopus_trigger_id_t tid;
91 octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD,
92 octopus_BINDING_RPC, OCT_ON_SET, NULL, NULL);
93 struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
96 snprintf(query, 99, "r'sem\\.%d\\.[0-9]+' { sem: %d }", id, id);
99 snprintf(lock_name, 99, "sem.%d", id);
101 // XXX: The current implementation suffers from a herd effect,
102 // may be worth it to use locks for this critical section
104 cl->call_seq.get(cl, query, t, &result, &tid, &err);
106 if (err_is_ok(err)) {
107 errval_t del_err = oct_del(result);
111 if (err_is_ok(del_err)) {
112 break; // Decreased successfully
114 else if (err_no(del_err) == OCT_ERR_NO_RECORD) {
115 continue; // Need to start over
118 break; // Unexpected error
121 else if (err_no(err) == OCT_ERR_NO_RECORD) {
122 // No record found, wait until one is posted
123 char* trigger_result = NULL;
124 uint64_t fn, mode, state;
125 cl->recv.trigger(cl, &tid, &fn, &mode, &trigger_result, &state);
126 free(trigger_result);
129 break; // Unexpected error
137 errval_t oct_sem_trywait(uint32_t id)
139 errval_t err = SYS_ERR_OK;
143 err = oct_get(&result, "r'sem\\.%d\\.[0-9]+' { sem: %d }", id, id);
144 if (err_is_ok(err)) {
145 err = oct_del(result);
147 else if (err_no(err) == OCT_ERR_NO_RECORD) {
148 // Return with no record error to caller