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

Reply via email to