Nope, on linux you can do it using standard (linux) libraries, since threads are actually implemented by the kernel with clone().
Here's a simple demo using clone for threads and semaphores for locks:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sched.h>
#define IDKEY 23003
#define SSZ 16384
struct thrinit {
int sid;
int tid;
int *data;
};
struct sembuf sopDown = {
.sem_num = 0, // array index
.sem_op = -1, // signed value! (see below)
.sem_flg = 0
};
struct sembuf sopUp = { 0, 1, 0 };
int thread (void *arg) {
struct thrinit *me = arg;
int i, r;
fprintf(stderr,"Start %d (count %d)\n",me->tid,*(me->data));
for (i=0;;i++) {
semop(me->sid,&sopDown,1);
r = semctl(me->sid,0,GETVAL);
if (*(me->data)>9) {
semop(me->sid,&sopUp,1);
break;
}
(*(me->data))++;
fprintf(stderr,"Thread %d-%d: count now %d sem_val=%d\n",me->tid,i,*(me->data),r);
semop(me->sid,&sopUp,1);
}
return 0;
}
int main(int argc, const char *argv[]) {
unsigned char *stacks[3];
struct thrinit threads[3];
int id = semget(IDKEY, 1, IPC_CREAT|0666),
i, count = 0;
if (id < 0) {
perror("semget() failed: ");
return -1;
}
semctl(id,0,SETVAL,1);
/* Confusing fact about sem value and the "sem_op" used by sopDown:
* one is unsigned, and the other is not. Up/down involves a comparison of
* ABSOLUTE values, then combination/subtraction. Qv. the open group man page for semop() */
for (i=0;i<3;i++) {
threads[i].sid = id;
threads[i].tid = i;
threads[i].data = &count;
stacks[i] = malloc(SSZ);
clone(thread,stacks[i]+SSZ-1,CLONE_VM|CLONE_SYSVSEM,(void*)&threads[i]);
fprintf(stderr, "issued %d\n", i);
}
while (1) {
sleep(1);
semop(id,&sopDown,1);
fprintf(stderr, "main(): count now %d\n",count);
if (count >= 9) break;
semop(id,&sopUp,1);
}
semop(id,&sopUp,1);
for (i=0;i<3;i++) free(stacks[i]);
return 0;
}
Output should be something like this:
issued 0
Start 1 (count 0)
Start 0 (count 0)
Thread 1-0: count now 1 sem_val=0
issued 1
Thread 0-0: count now 2 sem_val=0
Start 2 (count 1)
issued 2
Thread 1-1: count now 3 sem_val=0
Thread 2-0: count now 4 sem_val=0
Thread 0-1: count now 5 sem_val=0
Thread 1-2: count now 6 sem_val=0
Thread 2-1: count now 7 sem_val=0
Thread 0-2: count now 8 sem_val=0
Thread 1-3: count now 9 sem_val=0
Thread 2-2: count now 10 sem_val=0
main(): count now 10
altho as with all threads, there is no guarantee of the order of exectution. Sorry I was skimpy with the comments, if you are interested ask questions and I can explain.