Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 0315679 in mainline


Ignore:
Timestamp:
2009-07-06T19:40:46Z (12 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master
Children:
adb49f58
Parents:
5d96851
Message:

Move fully to IPC-based tracking of task startup and termination in NS. This also gets rid of the race condition present in the previous code.

Location:
uspace/srv/ns
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/ns/ns.c

    r5d96851 r0315679  
    109109                ipcarg_t retval;
    110110               
    111                 if (callid & IPC_CALLID_NOTIFICATION) {
    112                         id = (task_id_t)
    113                             MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call));
    114                         wait_notification((wait_type_t) IPC_GET_ARG1(call), id);
    115                         continue;
    116                 }
    117                
    118111                switch (IPC_GET_METHOD(call)) {
    119112                case IPC_M_SHARE_IN:
  • uspace/srv/ns/task.c

    r5d96851 r0315679  
    4949/* TODO:
    5050 *
    51  * The current implementation of waiting on a task is not perfect. If somebody
    52  * The caller has to make sure that it is not trying to wait
    53  * before the NS has a change to receive the task creation notification. This
    54  * can be assured by waiting for this event in task_spawn().
    55  *
    56  * Finally, as there is currently no convention that each task has to be waited
     51 * As there is currently no convention that each task has to be waited
    5752 * for, the NS can leak memory because of the zombie tasks.
    5853 *
     
    208203        }
    209204       
    210         if (event_subscribe(EVENT_WAIT, 0) != EOK)
    211                 printf(NAME ": Error registering wait notifications\n");
    212        
    213205        list_initialize(&pending_wait);
    214206       
     
    248240}
    249241
    250 static void fail_pending_wait(task_id_t id, int rc)
    251 {
    252         link_t *cur;
    253        
    254 loop:
    255         for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
    256                 pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
    257                
    258                 if (pr->id == id) {
    259                         if (!(pr->callid & IPC_CALLID_NOTIFICATION))
    260                                 ipc_answer_0(pr->callid, rc);
    261                
    262                         list_remove(cur);
    263                         free(pr);
    264                         goto loop;
    265                 }
    266         }
    267 }
    268 
    269 void wait_notification(wait_type_t et, task_id_t id)
    270 {
    271         unsigned long keys[2] = {
    272                 LOWER32(id),
    273                 UPPER32(id)
    274         };
    275        
    276         link_t *link = hash_table_find(&task_hash_table, keys);
    277        
    278         if (link == NULL) {
    279                 hashed_task_t *ht =
    280                     (hashed_task_t *) malloc(sizeof(hashed_task_t));
    281                 if (ht == NULL) {
    282                         fail_pending_wait(id, ENOMEM);
    283                         return;
    284                 }
    285                
    286                 link_initialize(&ht->link);
    287                 ht->id = id;
    288                 ht->destroyed = (et == TASK_CREATE) ? false : true;
    289                 ht->retval = -1;
    290                 hash_table_insert(&task_hash_table, keys, &ht->link);
    291         } else {
    292                 hashed_task_t *ht =
    293                     hash_table_get_instance(link, hashed_task_t, link);
    294                 ht->destroyed = (et == TASK_CREATE) ? false : true;
    295         }
    296 }
    297 
    298242void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid)
    299243{
     
    309253
    310254        if (ht == NULL) {
     255                /* No such task exists. */
    311256                retval = ENOENT;
    312257                goto out;
     
    339284{
    340285        task_id_t id;
    341         unsigned long keys[1];
     286        unsigned long keys[2];
    342287        link_t *link;
    343288        p2i_entry_t *e;
     289        hashed_task_t *ht;
    344290
    345291        id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
     
    354300        if (e == NULL)
    355301                return ENOMEM;
     302
     303        ht = (hashed_task_t *) malloc(sizeof(hashed_task_t));
     304        if (ht == NULL)
     305                return ENOMEM;
     306
     307        /* Insert to phone-to-id map. */
    356308
    357309        link_initialize(&e->link);
     
    360312        hash_table_insert(&phone_to_id, keys, &e->link);
    361313
     314        /* Insert to main table. */
     315
     316        keys[0] = LOWER32(id);
     317        keys[1] = UPPER32(id);
     318
     319        link_initialize(&ht->link);
     320        ht->id = id;
     321        ht->destroyed = false;
     322        ht->retval = -1;
     323        hash_table_insert(&task_hash_table, keys, &ht->link);
     324
    362325        return EOK;
    363326}
     
    390353int ns_task_disconnect(ipc_call_t *call)
    391354{
    392         unsigned long keys[1];
    393 
     355        unsigned long keys[2];
     356        task_id_t id;
     357        int rc;
     358
     359        rc = get_id_by_phone(call->in_phone_hash, &id);
     360        if (rc != EOK)
     361                return rc;
     362
     363        /* Delete from phone-to-id map. */
    394364        keys[0] = call->in_phone_hash;
    395365        hash_table_remove(&phone_to_id, keys, 1);
    396        
     366
     367        /* Mark task as finished. */
     368        keys[0] = LOWER32(id);
     369        keys[1] = UPPER32(id);
     370
     371        link_t *link = hash_table_find(&task_hash_table, keys);
     372        hashed_task_t *ht =
     373            hash_table_get_instance(link, hashed_task_t, link);
     374        assert(ht != NULL);
     375
     376        ht->destroyed = true;
     377
    397378        return EOK;
    398379}
Note: See TracChangeset for help on using the changeset viewer.