Re: mutex syscall patch, questions about clone and its possible bugs

RAMPOD SW Development (msmith@quix.robins.af.mil)
Sun, 12 May 1996 20:42:49 -0400 (EDT)


I'm implementing a POSIX threads package using clone()
for the system threads. It is working fine for me. Follows
is a sample for creating a system thread although I'm not
claiming it doesn't have problems. I hope we can hold off
on the kernel pthread patches because it seems that there
are several parties working on system threads. I would like
to provide a real hybrid user/system thread engine rather
than use MIT threads that are shipping with libc, but that
isn't up to me so... :)

/*
* Cheesy thread.
* Linux kernel 1.3.98
*
* Melvin Smith 1996
*/

#include <linux/pthread.h>
#include <linux/unistd.h>

/* Create a thread */

int pthread_create( pthread_t *tid, const pthread_attr_t *attr,
void (*start_fun)(void *), void *arg )
{
int retval = 0;
void **stack;
int stacksize;

if( attr == 0 )
stacksize = DEFAULT_STACK_SIZE;
else
stacksize = attr->stacksize;

/*
* Create the new thread's stack
*/
stack = (void **)malloc( stacksize );
if( !stack )
{
errno = ENOMEM;
return -1;
}

/*
* Push the arg onto stack
*/
stack = (void **)( (char *)stack + stacksize );

*--stack = arg;

/*
* Trap to clone() system call
* %eax - __NR_clone, system call number (linux/unistd.h)
* %ebx - clone flags
* %ecx - new stack for thread (process)
* Return value:
* %eax - pid of child process for parent, 0 for child
*/

__asm__ __volatile__ (
"int $0x80\n\t"
"testl %0,%0\n\t" /* return val ( 0=child,other=parent ) */
"jne parent\n\t"
"call *%3\n\t" /* call start fun() for child */
"movl %2,%0\n\t" /* exit() system call number */
"int $0x80\n\t" /* exit */
"parent:\t"
:"=a" (retval)
:"0" (__NR_clone),
"i" (__NR_exit),
"r" (start_fun),
"b" (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD),
"c" (stack)
);

if( retval > 0 )
{
*tid = retval;
}
else
{
errno = -retval;
retval = -1;
}

return retval;
}

[* REST OF CODE SNIPPED *]

Here is a test main.

/** TEST MAIN **/

void task1( void * );
void task2( void * );

int val;

int main()
{
pthread_t tid1;
pthread_t tid2;

if( pthread_create( &tid1, 0, task1, 0 ) < 0 )
printf( "thread creation failed errno %d\n", errno );

printf( "created thread 1\n" );

if( pthread_create( &tid1, 0, task2, 0 ) < 0 )
printf( "thread creation failed errno %d\n", errno );

printf( "created thread 2\n" );
exit(0);
}

void task1( void * arg )
{
while( 1 )
{
printf( "T1 Inc to %d\n", val++ );
sleep( 1 );
}
}

void task2( void * arg )
{
while( 1 )
{
printf( "T2 Inc to %d\n", val++ );
sleep( 1 );
}
}