On 13.07.2013 14:53:10, Jiří Zárevúcky wrote:
> So, basically, you want the calling thread to block until the target
> thread terminates. Then the calling thread cleans up the terminated
> thread's resources (if applicable) and returns its exit value (if
> present). Note that some/most API's provide also a detach() function,
> which says that no other thread will call join on the calling one.
> Normally, joining a terminated thread is required to avoid memory
> leaks.
Thanks. I was hoping to get such a good answer.
I have read the relevant kernel code and found out that the kernel
already contains everything needed to implement the new system call; it
even includes a thread_join macro. So I did. I made a patch and a
ChangeLog if somebody is interested to test this on their own
development branch. I'm sending it as an attachment. I did not find a
way to get thread's exit status; I read in the comments of
thread_exit(): "Exit status. Currently not used.", so I'm returning 0
if everything went OK and ENOENT if thread ID is not found. Also in the
comments of __thread_main() I read: "This function is called from
__thread_entry() and is used to call the thread's implementing function
and perform cleanup and exit when thread returns back." So, I did not
write explicit code in the sys_thread_join() to do cleanup of the
terminated thread. Please, if somebody reads my patch, I welcome any
comments on this.
As I am new to programming threads I am not sure if I correctly tested
the new system call. I wrote some code like this:
void thread_test(void)
{
if (thread_create(implement_thread1, NULL,
"test_thread1", NULL) < 0)
printf("Could not create thread.\n");
}
void implement_thread1(void *data)
{
printf("%d\n", thread_join(thread_get_id()));
}
thread_join returns 0 in this case, but I am not sure if this is a
proof that the system call works correctly. Please, if somebody finds a
better way to test sys_thread_join(), I would be thankful if I could
see the code.* kernel/generic/src/syscall/syscall.c (sys_thread_join): New system call.
* kernel/generic/src/proc/thread.c (sys_thread_join): Implement new system call.
* kernel/generic/include/proc/thread.h (sys_thread_join): Add prototype.
* abi/include/abi/syscall.h: Add the new system call to syscall_t.
* uspace/lib/c/generic/thread.c (thread_join): Implement the function.
=== modified file 'abi/include/abi/syscall.h'
--- abi/include/abi/syscall.h 2012-08-12 18:57:22 +0000
+++ abi/include/abi/syscall.h 2013-07-13 20:33:29 +0000
@@ -44,6 +44,7 @@
SYS_THREAD_GET_ID,
SYS_THREAD_USLEEP,
SYS_THREAD_UDELAY,
+ SYS_THREAD_JOIN,
SYS_TASK_GET_ID,
SYS_TASK_SET_NAME,
=== modified file 'kernel/generic/include/proc/thread.h'
--- kernel/generic/include/proc/thread.h 2012-06-20 16:18:37 +0000
+++ kernel/generic/include/proc/thread.h 2013-07-13 20:29:11 +0000
@@ -261,6 +261,7 @@
extern sysarg_t sys_thread_get_id(thread_id_t *);
extern sysarg_t sys_thread_usleep(uint32_t);
extern sysarg_t sys_thread_udelay(uint32_t);
+extern sysarg_t sys_thread_join(thread_id_t);
#endif
=== modified file 'kernel/generic/src/proc/thread.c'
--- kernel/generic/src/proc/thread.c 2012-06-20 23:52:58 +0000
+++ kernel/generic/src/proc/thread.c 2013-07-14 11:42:17 +0000
@@ -971,5 +971,30 @@
return 0;
}
+/** Process syscall to join thread.
+ *
+ */
+sysarg_t sys_thread_join(thread_id_t thread_id)
+{
+ thread_t *target_thread;
+
+ /* Avoid deadlock */
+ ipl_t ipl = interrupts_disable();
+ irq_spinlock_lock(&threads_lock, true);
+
+ if ((target_thread = thread_find_by_id(thread_id)) == NULL) {
+ /* No such thread ID */
+ irq_spinlock_unlock(&threads_lock, true);
+ interrupts_restore(ipl);
+ return ENOENT;
+ }
+ else {
+ irq_spinlock_unlock(&threads_lock, true);
+ interrupts_restore(ipl);
+ thread_join(target_thread);
+ return 0;
+ }
+}
+
/** @}
*/
=== modified file 'kernel/generic/src/syscall/syscall.c'
--- kernel/generic/src/syscall/syscall.c 2012-08-12 18:57:22 +0000
+++ kernel/generic/src/syscall/syscall.c 2013-07-13 20:14:00 +0000
@@ -128,6 +128,7 @@
(syshandler_t) sys_thread_get_id,
(syshandler_t) sys_thread_usleep,
(syshandler_t) sys_thread_udelay,
+ (syshandler_t) sys_thread_join,
(syshandler_t) sys_task_get_id,
(syshandler_t) sys_task_set_name,
=== modified file 'uspace/lib/c/generic/thread.c'
--- uspace/lib/c/generic/thread.c 2012-11-18 20:00:33 +0000
+++ uspace/lib/c/generic/thread.c 2013-07-14 08:32:47 +0000
@@ -153,15 +153,13 @@
/** Join thread.
*
- * Currently not implemented.
- *
* @param thread TID.
*
- * @return Thread exit status.
+ * @return Thread exit status or a code from @ref errno.h on failure.
*/
-int thread_join(thread_id_t thread)
+int thread_join(thread_id_t thread_id)
{
- return 0;
+ return __SYSCALL1(SYS_THREAD_JOIN, (sysarg_t) thread_id);
}
/** Get current thread ID.
_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/listinfo/helenos-devel