source: mainline/uspace/srv/ns/task.c@ b83c5e4

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b83c5e4 was 5e801dc, checked in by GitHub <noreply@…>, 6 years ago

Indicate and enforce constness of hash table key in certain functions (#158)

The assumption here is that modifying key in the hash/equal functions in something completely unexpected, and not something you would ever want to do intentionally, so it makes sense to disallow it entirely to get that extra level of checking.

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[40313e4]1/*
2 * Copyright (c) 2009 Martin Decky
[5d96851b]3 * Copyright (c) 2009 Jiri Svoboda
[40313e4]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup ns
31 * @{
32 */
33
[d9c8c81]34#include <adt/hash_table.h>
[7b616e2]35#include <async.h>
[3e6a98c5]36#include <stdbool.h>
[40313e4]37#include <errno.h>
38#include <assert.h>
39#include <macros.h>
[38d150e]40#include <stdio.h>
41#include <stdlib.h>
[1c635d6]42#include <types/task.h>
[40313e4]43#include "task.h"
44#include "ns.h"
45
46/** Task hash table item. */
47typedef struct {
[062d900]48 ht_link_t link;
[a35b458]49
[007e6efa]50 task_id_t id; /**< Task ID. */
51 bool finished; /**< Task is done. */
52 bool have_rval; /**< Task returned a value. */
53 int retval; /**< The return value. */
[40313e4]54} hashed_task_t;
55
[5e801dc]56static size_t task_key_hash(const void *key)
[40313e4]57{
[5e801dc]58 const task_id_t *tid = key;
59 return *tid;
[40313e4]60}
61
[5e801dc]62static size_t task_hash(const ht_link_t *item)
[40313e4]63{
[062d900]64 hashed_task_t *ht = hash_table_get_inst(item, hashed_task_t, link);
65 return ht->id;
[40313e4]66}
67
[5e801dc]68static bool task_key_equal(const void *key, const ht_link_t *item)
[40313e4]69{
[5e801dc]70 const task_id_t *tid = key;
[062d900]71 hashed_task_t *ht = hash_table_get_inst(item, hashed_task_t, link);
[5e801dc]72 return ht->id == *tid;
[062d900]73}
74
75/** Perform actions after removal of item from the hash table. */
76static void task_remove(ht_link_t *item)
77{
78 free(hash_table_get_inst(item, hashed_task_t, link));
[40313e4]79}
80
81/** Operations for task hash table. */
[062d900]82static hash_table_ops_t task_hash_table_ops = {
[40313e4]83 .hash = task_hash,
[062d900]84 .key_hash = task_key_hash,
85 .key_equal = task_key_equal,
[4e00f87]86 .equal = NULL,
[40313e4]87 .remove_callback = task_remove
88};
89
90/** Task hash table structure. */
91static hash_table_t task_hash_table;
92
[5d96851b]93typedef struct {
[062d900]94 ht_link_t link;
[6769005]95 sysarg_t label; /**< Incoming phone label. */
96 task_id_t id; /**< Task ID. */
[5d96851b]97} p2i_entry_t;
98
[6769005]99/* label-to-id hash table operations */
[062d900]100
[5e801dc]101static size_t p2i_key_hash(const void *key)
[5d96851b]102{
[5e801dc]103 const sysarg_t *label = key;
104 return *label;
[5d96851b]105}
106
[062d900]107static size_t p2i_hash(const ht_link_t *item)
[5d96851b]108{
[062d900]109 p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link);
[6769005]110 return entry->label;
[062d900]111}
112
[5e801dc]113static bool p2i_key_equal(const void *key, const ht_link_t *item)
[062d900]114{
[5e801dc]115 const sysarg_t *label = key;
[062d900]116 p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link);
[a35b458]117
[5e801dc]118 return (*label == entry->label);
[5d96851b]119}
120
121/** Perform actions after removal of item from the hash table.
122 *
123 * @param item Item that was removed from the hash table.
124 *
125 */
[062d900]126static void p2i_remove(ht_link_t *item)
[5d96851b]127{
128 assert(item);
[062d900]129 free(hash_table_get_inst(item, p2i_entry_t, link));
[5d96851b]130}
131
132/** Operations for task hash table. */
[062d900]133static hash_table_ops_t p2i_ops = {
[5d96851b]134 .hash = p2i_hash,
[062d900]135 .key_hash = p2i_key_hash,
136 .key_equal = p2i_key_equal,
[4e00f87]137 .equal = NULL,
[5d96851b]138 .remove_callback = p2i_remove
139};
140
[6769005]141/** Map phone label to task ID */
[5d96851b]142static hash_table_t phone_to_id;
143
[40313e4]144/** Pending task wait structure. */
145typedef struct {
146 link_t link;
[984a9ba]147 task_id_t id; /**< Task ID */
148 ipc_call_t call; /**< Call waiting for the connection */
[40313e4]149} pending_wait_t;
150
[b72efe8]151static list_t pending_wait;
[40313e4]152
[b7fd2a0]153errno_t task_init(void)
[40313e4]154{
[062d900]155 if (!hash_table_create(&task_hash_table, 0, 0, &task_hash_table_ops)) {
[40313e4]156 printf(NAME ": No memory available for tasks\n");
157 return ENOMEM;
158 }
[a35b458]159
[062d900]160 if (!hash_table_create(&phone_to_id, 0, 0, &p2i_ops)) {
[5d96851b]161 printf(NAME ": No memory available for tasks\n");
162 return ENOMEM;
163 }
[a35b458]164
[40313e4]165 list_initialize(&pending_wait);
166 return EOK;
167}
168
169/** Process pending wait requests */
170void process_pending_wait(void)
171{
[adb49f58]172 task_exit_t texit;
[a35b458]173
[40313e4]174loop:
[feeac0d]175 list_foreach(pending_wait, link, pending_wait_t, pr) {
[062d900]176 ht_link_t *link = hash_table_find(&task_hash_table, &pr->id);
[40313e4]177 if (!link)
178 continue;
[a35b458]179
[062d900]180 hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link);
[adb49f58]181 if (!ht->finished)
[40313e4]182 continue;
[a35b458]183
[7b616e2]184 texit = ht->have_rval ? TASK_EXIT_NORMAL :
185 TASK_EXIT_UNEXPECTED;
[984a9ba]186 async_answer_2(&pr->call, EOK, texit, ht->retval);
[a35b458]187
[feeac0d]188 list_remove(&pr->link);
[40313e4]189 free(pr);
190 goto loop;
191 }
192}
193
[984a9ba]194void wait_for_task(task_id_t id, ipc_call_t *call)
[40313e4]195{
[062d900]196 ht_link_t *link = hash_table_find(&task_hash_table, &id);
[40313e4]197 hashed_task_t *ht = (link != NULL) ?
[062d900]198 hash_table_get_inst(link, hashed_task_t, link) : NULL;
[a35b458]199
[5d96851b]200 if (ht == NULL) {
[0315679]201 /* No such task exists. */
[984a9ba]202 async_answer_0(call, ENOENT);
[475fe35]203 return;
[5d96851b]204 }
[a35b458]205
[1c635d6]206 if (ht->finished) {
207 task_exit_t texit = ht->have_rval ? TASK_EXIT_NORMAL :
208 TASK_EXIT_UNEXPECTED;
[984a9ba]209 async_answer_2(call, EOK, texit, ht->retval);
[40313e4]210 return;
211 }
[a35b458]212
[1c635d6]213 /* Add to pending list */
214 pending_wait_t *pr =
215 (pending_wait_t *) malloc(sizeof(pending_wait_t));
216 if (!pr) {
[984a9ba]217 async_answer_0(call, ENOMEM);
[1c635d6]218 return;
[adb49f58]219 }
[a35b458]220
[1c635d6]221 link_initialize(&pr->link);
222 pr->id = id;
[984a9ba]223 pr->call = *call;
[1c635d6]224 list_append(&pr->link, &pending_wait);
[7114d83]225}
226
[b7fd2a0]227errno_t ns_task_id_intro(ipc_call_t *call)
[5d96851b]228{
[fafb8e5]229 task_id_t id = MERGE_LOUP32(ipc_get_arg1(call), ipc_get_arg2(call));
[a35b458]230
[6769005]231 ht_link_t *link = hash_table_find(&phone_to_id, &call->request_label);
[5d96851b]232 if (link != NULL)
[8a637a4]233 return EEXIST;
[a35b458]234
[007e6efa]235 p2i_entry_t *entry = (p2i_entry_t *) malloc(sizeof(p2i_entry_t));
236 if (entry == NULL)
[5d96851b]237 return ENOMEM;
[a35b458]238
[007e6efa]239 hashed_task_t *ht = (hashed_task_t *) malloc(sizeof(hashed_task_t));
[234f47e]240 if (ht == NULL) {
241 free(entry);
[0315679]242 return ENOMEM;
[234f47e]243 }
[a35b458]244
[007e6efa]245 /*
246 * Insert into the phone-to-id map.
247 */
[a35b458]248
[6769005]249 assert(call->request_label);
250 entry->label = call->request_label;
[007e6efa]251 entry->id = id;
[062d900]252 hash_table_insert(&phone_to_id, &entry->link);
[a35b458]253
[007e6efa]254 /*
255 * Insert into the main table.
256 */
[a35b458]257
[0315679]258 ht->id = id;
[adb49f58]259 ht->finished = false;
260 ht->have_rval = false;
[0315679]261 ht->retval = -1;
[062d900]262 hash_table_insert(&task_hash_table, &ht->link);
[a35b458]263
[007e6efa]264 return EOK;
265}
[0315679]266
[6769005]267static errno_t get_id_by_phone(sysarg_t label, task_id_t *id)
[007e6efa]268{
[6769005]269 assert(label);
270 ht_link_t *link = hash_table_find(&phone_to_id, &label);
[007e6efa]271 if (link == NULL)
272 return ENOENT;
[a35b458]273
[062d900]274 p2i_entry_t *entry = hash_table_get_inst(link, p2i_entry_t, link);
[007e6efa]275 *id = entry->id;
[a35b458]276
[5d96851b]277 return EOK;
278}
279
[b7fd2a0]280errno_t ns_task_retval(ipc_call_t *call)
[7114d83]281{
[6769005]282 task_id_t id = call->task_id;
[a35b458]283
[062d900]284 ht_link_t *link = hash_table_find(&task_hash_table, &id);
[7114d83]285 hashed_task_t *ht = (link != NULL) ?
[062d900]286 hash_table_get_inst(link, hashed_task_t, link) : NULL;
[a35b458]287
[007e6efa]288 if ((ht == NULL) || (ht->finished))
[7114d83]289 return EINVAL;
[a35b458]290
[adb49f58]291 ht->finished = true;
292 ht->have_rval = true;
[fafb8e5]293 ht->retval = ipc_get_arg1(call);
[a35b458]294
[1c635d6]295 process_pending_wait();
[a35b458]296
[5d96851b]297 return EOK;
298}
299
[b7fd2a0]300errno_t ns_task_disconnect(ipc_call_t *call)
[5d96851b]301{
[0315679]302 task_id_t id;
[6769005]303 errno_t rc = get_id_by_phone(call->request_label, &id);
[0315679]304 if (rc != EOK)
305 return rc;
[a35b458]306
[0315679]307 /* Delete from phone-to-id map. */
[6769005]308 hash_table_remove(&phone_to_id, &call->request_label);
[a35b458]309
[0315679]310 /* Mark task as finished. */
[062d900]311 ht_link_t *link = hash_table_find(&task_hash_table, &id);
312 if (link == NULL)
[adb49f58]313 return EOK;
[062d900]314
315 hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link);
[a35b458]316
[adb49f58]317 ht->finished = true;
[a35b458]318
[1c635d6]319 process_pending_wait();
320 hash_table_remove(&task_hash_table, &id);
[a35b458]321
[7114d83]322 return EOK;
[40313e4]323}
324
325/**
326 * @}
327 */
Note: See TracBrowser for help on using the repository browser.