Changeset 07d4271 in mainline
- Timestamp:
- 2024-01-25T16:22:55Z (13 months ago)
- Branches:
- master
- Children:
- f8b69a1e
- Parents:
- 1a1e124
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2024-01-25 15:56:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2024-01-25 16:22:55)
- Location:
- kernel/generic
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/proc/task.h
r1a1e124 r07d4271 88 88 89 89 /** Number of references (i.e. threads). */ 90 atomic_ size_t refcount;90 atomic_refcount_t refcount; 91 91 /** Number of threads that haven't exited yet. */ 92 92 // TODO: remove … … 144 144 extern void task_done(void); 145 145 extern task_t *task_create(as_t *, const char *); 146 extern void task_destroy(task_t *);147 146 extern void task_hold(task_t *); 148 147 extern void task_release(task_t *); -
kernel/generic/src/ddi/ddi.c
r1a1e124 r07d4271 336 336 return EPERM; 337 337 338 irq_spinlock_lock(&tasks_lock, true);339 340 338 task_t *task = task_find_by_id(id); 341 339 342 if ((!task) || (!container_check(CONTAINER, task->container))) { 343 /* 344 * There is no task with the specified ID 345 * or the task belongs to a different security 346 * context. 347 */ 348 irq_spinlock_unlock(&tasks_lock, true); 340 if (!task) 349 341 return ENOENT; 350 } 351 352 /* Lock the task and release the lock protecting tasks dictionary. */ 353 irq_spinlock_exchange(&tasks_lock, &task->lock); 354 errno_t rc = ddi_iospace_enable_arch(task, ioaddr, size); 342 343 errno_t rc = ENOENT; 344 345 irq_spinlock_lock(&task->lock, true); 346 347 /* Check that the task belongs to the correct security context. */ 348 if (container_check(CONTAINER, task->container)) 349 rc = ddi_iospace_enable_arch(task, ioaddr, size); 350 355 351 irq_spinlock_unlock(&task->lock, true); 356 352 task_release(task); 357 353 return rc; 358 354 } … … 377 373 return EPERM; 378 374 379 irq_spinlock_lock(&tasks_lock, true);380 381 375 task_t *task = task_find_by_id(id); 382 376 383 if ((!task) || (!container_check(CONTAINER, task->container))) { 384 /* 385 * There is no task with the specified ID 386 * or the task belongs to a different security 387 * context. 388 */ 389 irq_spinlock_unlock(&tasks_lock, true); 377 if (!task) 390 378 return ENOENT; 391 } 392 393 /* Lock the task and release the lock protecting tasks dictionary. */ 394 irq_spinlock_exchange(&tasks_lock, &task->lock); 395 errno_t rc = ddi_iospace_disable_arch(task, ioaddr, size); 379 380 errno_t rc = ENOENT; 381 382 irq_spinlock_lock(&task->lock, true); 383 384 /* Check that the task belongs to the correct security context. */ 385 if (container_check(CONTAINER, task->container)) 386 rc = ddi_iospace_disable_arch(task, ioaddr, size); 387 396 388 irq_spinlock_unlock(&task->lock, true); 397 389 task_release(task); 398 390 return rc; 399 391 } -
kernel/generic/src/ipc/ipc.c
r1a1e124 r07d4271 967 967 void ipc_print_task(task_id_t taskid) 968 968 { 969 irq_spinlock_lock(&tasks_lock, true);970 969 task_t *task = task_find_by_id(taskid); 971 if (!task) { 972 irq_spinlock_unlock(&tasks_lock, true); 970 if (!task) 973 971 return; 974 }975 task_hold(task);976 irq_spinlock_unlock(&tasks_lock, true);977 972 978 973 printf("[phone cap] [calls] [state\n"); -
kernel/generic/src/ipc/kbox.c
r1a1e124 r07d4271 200 200 /** Connect phone to a task kernel-box specified by id. 201 201 * 202 * Note that this is not completely atomic. For optimisation reasons, the task203 * might start cleaning up kbox after the phone has been connected and before204 * a kbox thread has been created. This must be taken into account in the205 * cleanup code.206 *207 202 * @param[out] out_phone Phone capability handle on success. 208 203 * @return Error code. … … 211 206 errno_t ipc_connect_kbox(task_id_t taskid, cap_phone_handle_t *out_phone) 212 207 { 213 irq_spinlock_lock(&tasks_lock, true);214 215 208 task_t *task = task_find_by_id(taskid); 216 if (task == NULL) { 217 irq_spinlock_unlock(&tasks_lock, true); 209 if (!task) 218 210 return ENOENT; 219 }220 221 atomic_inc(&task->refcount);222 223 irq_spinlock_unlock(&tasks_lock, true);224 211 225 212 mutex_lock(&task->kb.cleanup_lock); 226 227 if (atomic_predec(&task->refcount) == 0) {228 mutex_unlock(&task->kb.cleanup_lock);229 task_destroy(task);230 return ENOENT;231 }232 213 233 214 if (task->kb.finished) { 234 215 mutex_unlock(&task->kb.cleanup_lock); 216 task_release(task); 235 217 return EINVAL; 236 218 } … … 243 225 if (!kb_thread) { 244 226 mutex_unlock(&task->kb.cleanup_lock); 227 task_release(task); 245 228 return ENOMEM; 246 229 } … … 255 238 if (rc != EOK) { 256 239 mutex_unlock(&task->kb.cleanup_lock); 240 task_release(task); 257 241 return rc; 258 242 } … … 265 249 266 250 mutex_unlock(&task->kb.cleanup_lock); 251 task_release(task); 267 252 *out_phone = phone_handle; 268 253 return EOK; -
kernel/generic/src/proc/program.c
r1a1e124 r07d4271 99 99 if (!area) { 100 100 free(kernel_uarg); 101 task_ destroy(prg->task);101 task_release(prg->task); 102 102 prg->task = NULL; 103 103 return ENOMEM; … … 119 119 free(kernel_uarg); 120 120 as_area_destroy(as, virt); 121 task_ destroy(prg->task);121 task_release(prg->task); 122 122 prg->task = NULL; 123 123 return ELIMIT; -
kernel/generic/src/proc/task.c
r1a1e124 r07d4271 158 158 return rc; 159 159 160 atomic_store(&task->refcount, 0);161 160 atomic_store(&task->lifecount, 0); 162 161 … … 201 200 if (!task) 202 201 return NULL; 202 203 refcount_init(&task->refcount); 203 204 204 205 task_create_arch(task); … … 268 269 * 269 270 */ 270 void task_destroy(task_t *task)271 static void task_destroy(task_t *task) 271 272 { 272 273 /* … … 299 300 void task_hold(task_t *task) 300 301 { 301 atomic_inc(&task->refcount);302 refcount_up(&task->refcount); 302 303 } 303 304 … … 311 312 void task_release(task_t *task) 312 313 { 313 if ( (atomic_predec(&task->refcount)) == 0)314 if (refcount_down(&task->refcount)) 314 315 task_destroy(task); 315 316 } … … 416 417 /** Find task structure corresponding to task ID. 417 418 * 418 * The tasks_lock must be already held by the caller of this function and419 * interrupts must be disabled.420 *421 419 * @param id Task ID. 422 420 * 423 * @return Task structure addressor NULL if there is no such task ID.421 * @return Task reference or NULL if there is no such task ID. 424 422 * 425 423 */ 426 424 task_t *task_find_by_id(task_id_t id) 427 425 { 428 assert(interrupts_disabled()); 429 assert(irq_spinlock_locked(&tasks_lock)); 426 task_t *task = NULL; 427 428 irq_spinlock_lock(&tasks_lock, true); 430 429 431 430 odlink_t *odlink = odict_find_eq(&tasks, &id, NULL); 432 if (odlink != NULL) 433 return odict_get_instance(odlink, task_t, ltasks); 434 435 return NULL; 431 if (odlink != NULL) { 432 task = odict_get_instance(odlink, task_t, ltasks); 433 434 /* 435 * The directory of tasks can't hold a reference, since that would 436 * prevent task from ever being destroyed. That means we have to 437 * check for the case where the task is already being destroyed, but 438 * not yet removed from the directory. 439 */ 440 if (!refcount_try_up(&task->refcount)) 441 task = NULL; 442 } 443 444 irq_spinlock_unlock(&tasks_lock, true); 445 446 return task; 436 447 } 437 448 … … 524 535 static void task_kill_internal(task_t *task) 525 536 { 526 irq_spinlock_lock(&task->lock, false);537 irq_spinlock_lock(&task->lock, true); 527 538 528 539 /* … … 534 545 } 535 546 536 irq_spinlock_unlock(&task->lock, false);547 irq_spinlock_unlock(&task->lock, true); 537 548 } 538 549 … … 552 563 return EPERM; 553 564 554 irq_spinlock_lock(&tasks_lock, true);555 556 565 task_t *task = task_find_by_id(id); 557 if (!task) { 558 irq_spinlock_unlock(&tasks_lock, true); 566 if (!task) 559 567 return ENOENT; 560 }561 568 562 569 task_kill_internal(task); 563 irq_spinlock_unlock(&tasks_lock, true); 564 570 task_release(task); 565 571 return EOK; 566 572 } … … 592 598 } 593 599 594 irq_spinlock_lock(&tasks_lock, true);595 600 task_kill_internal(TASK); 596 irq_spinlock_unlock(&tasks_lock, true);597 598 601 thread_exit(); 599 602 } … … 624 627 if (additional) 625 628 printf("%-8" PRIu64 " %9zu", task->taskid, 626 atomic_load(&task-> refcount));629 atomic_load(&task->lifecount)); 627 630 else 628 631 printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p" … … 636 639 printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c " 637 640 "%9zu\n", task->taskid, ucycles, usuffix, kcycles, 638 ksuffix, atomic_load(&task-> refcount));641 ksuffix, atomic_load(&task->lifecount)); 639 642 else 640 643 printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n", -
kernel/generic/src/security/perm.c
r1a1e124 r07d4271 89 89 return EPERM; 90 90 91 irq_spinlock_lock(&tasks_lock, true);92 91 task_t *task = task_find_by_id(taskid); 93 94 if ((!task) || (!container_check(CONTAINER, task->container))) { 95 irq_spinlock_unlock(&tasks_lock, true); 92 if (!task) 96 93 return ENOENT; 94 95 errno_t rc = ENOENT; 96 97 irq_spinlock_lock(&task->lock, true); 98 if (container_check(CONTAINER, task->container)) { 99 task->perms |= perms; 100 rc = EOK; 97 101 } 98 99 irq_spinlock_lock(&task->lock, false); 100 task->perms |= perms; 101 irq_spinlock_unlock(&task->lock, false); 102 103 irq_spinlock_unlock(&tasks_lock, true); 104 return EOK; 102 irq_spinlock_unlock(&task->lock, true); 103 104 task_release(task); 105 return rc; 105 106 } 106 107 … … 118 119 static errno_t perm_revoke(task_id_t taskid, perm_t perms) 119 120 { 120 irq_spinlock_lock(&tasks_lock, true);121 122 121 task_t *task = task_find_by_id(taskid); 123 if ((!task) || (!container_check(CONTAINER, task->container))) { 124 irq_spinlock_unlock(&tasks_lock, true); 122 if (!task) 125 123 return ENOENT; 126 }127 124 128 125 /* … … 131 128 * doesn't have PERM_PERM. 132 129 */ 133 irq_spinlock_lock(&TASK->lock, false); 134 135 if ((!(TASK->perms & PERM_PERM)) || (task != TASK)) { 136 irq_spinlock_unlock(&TASK->lock, false); 137 irq_spinlock_unlock(&tasks_lock, true); 130 if (task != TASK && !(perm_get(TASK) & PERM_PERM)) { 131 task_release(task); 138 132 return EPERM; 139 133 } 140 134 141 task->perms &= ~perms; 142 irq_spinlock_unlock(&TASK->lock, false); 143 144 irq_spinlock_unlock(&tasks_lock, true); 145 return EOK; 135 errno_t rc = ENOENT; 136 137 irq_spinlock_lock(&task->lock, true); 138 if (container_check(CONTAINER, task->container)) { 139 task->perms &= ~perms; 140 rc = EOK; 141 } 142 irq_spinlock_unlock(&task->lock, true); 143 144 task_release(task); 145 return rc; 146 146 } 147 147 -
kernel/generic/src/sysinfo/stats.c
r1a1e124 r07d4271 221 221 stats_task->virtmem = get_task_virtmem(task->as); 222 222 stats_task->resmem = get_task_resmem(task->as); 223 stats_task->threads = atomic_load(&task-> refcount);223 stats_task->threads = atomic_load(&task->lifecount); 224 224 task_get_accounting(task, &(stats_task->ucycles), 225 225 &(stats_task->kcycles)); … … 511 511 { 512 512 /* Initially no return value */ 513 sysinfo_return_t ret; 514 ret.tag = SYSINFO_VAL_UNDEFINED; 513 sysinfo_return_t ret = { 514 .tag = SYSINFO_VAL_UNDEFINED, 515 }; 515 516 516 517 /* Parse the task ID */ … … 519 520 return ret; 520 521 521 /* Messing with task structures, avoid deadlock */522 irq_spinlock_lock(&tasks_lock, true);523 524 522 task_t *task = task_find_by_id(task_id); 525 if (task == NULL) { 526 /* No task with this ID */ 527 irq_spinlock_unlock(&tasks_lock, true); 523 if (!task) 528 524 return ret; 529 }530 525 531 526 if (dry_run) { … … 533 528 ret.data.data = NULL; 534 529 ret.data.size = sizeof(stats_task_t); 535 536 irq_spinlock_unlock(&tasks_lock, true);537 530 } else { 538 531 /* Allocate stats_task_t structure */ 539 stats_task_t *stats_task = 540 (stats_task_t *) malloc(sizeof(stats_task_t)); 541 if (stats_task == NULL) { 542 irq_spinlock_unlock(&tasks_lock, true); 543 return ret; 532 stats_task_t *stats_task = malloc(sizeof(stats_task_t)); 533 534 if (stats_task != NULL) { 535 /* Correct return value */ 536 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 537 ret.data.data = stats_task; 538 ret.data.size = sizeof(stats_task_t); 539 540 irq_spinlock_lock(&task->lock, true); 541 produce_stats_task(task, stats_task); 542 irq_spinlock_unlock(&task->lock, true); 544 543 } 545 546 /* Correct return value */ 547 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 548 ret.data.data = (void *) stats_task; 549 ret.data.size = sizeof(stats_task_t); 550 551 /* Hand-over-hand locking */ 552 irq_spinlock_exchange(&tasks_lock, &task->lock); 553 554 produce_stats_task(task, stats_task); 555 556 irq_spinlock_unlock(&task->lock, true); 557 } 558 544 } 545 546 task_release(task); 559 547 return ret; 560 548 }
Note:
See TracChangeset
for help on using the changeset viewer.