#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
 
 
#define PID_MIN  	0
#define PID_MAX 	3
 
#define NUM_THREADS 100
#define ITERATIONS	10
#define SLEEP		5
 
 
 
 
int S;
 
/* mutex lock for accessing pid_map */
pthread_mutex_t mutex;
 
int pid_map[PID_MAX-PID_MIN+1];
int thread_counter =0;
 
 
int allocate_map(void);
int allocate_pid(int thread_id);
void release_pid(int pid);
 
 
 
 // Allocates the pid map.
 
int allocate_map(void) 
{
	/*initilize to zero explicitly just to make sure*/
	int i;
	for (i =0;i<PID_MAX-PID_MIN+1;i++)
	{
		pid_map[i] = 0;
		S++;
 
	}
	printf("map allocated!S=%d\n",S
); 	return 1;
}
 
/**
 * Allocates a pid
 */
int allocate_pid(int t_id)
{
	int next_pid;
	int i,j;
	int err;
 
	for (j=0;j<PID_MAX-PID_MIN+1;j++)
		{
		}
 
 
	printf("Thread %d trying to lock...%d\n",t_id
,pthread_mutex_lock
(&mutex
)); 	S--;
 
	for (i =0;i<PID_MAX-PID_MIN;i++)
		{
			if (pid_map[i] == 0)
				{
					pid_map[i] = 1;
					next_pid=i;
					pthread_mutex_unlock(&mutex);
					return next_pid+PID_MIN;
 
 
 
				}
		}
	return -999;
 
}
/**
 * Releases a pid
 */
void release_pid(int pid)
{
	pid = pid-PID_MIN;
	pid_map[pid] = 0;
	S++;
}
 
void *do_something(void *threadid)
	{
		int  my_pid;
		long thread_id;
		int i;
		double r;
		thread_id= (long)threadid;
		//printf("\nthread %d launched do_something\n", thread_id);
		for (i=0;i<1;i++)
		{
			r=r/10;
			//r=0.1;
			//printf("thread %d trying to allocate PID..., S=%d\n",thread_id,S);
			my_pid=allocate_pid(thread_id);
 
			printf("Thread number %d got PID %d S=%d\n", thread_id
, my_pid
,S
); 			sleep(r);
			release_pid(my_pid);
 
			printf("Thread number %d released PID %d S=%d \n", thread_id
, my_pid
,S
);  
		}
 
		thread_counter--;
		return;
	}
 
 
int main()
{
	int i,err;
	time_t t;
 
	pthread_t tid[NUM_THREADS];
	if (pthread_mutex_init(&mutex, NULL) != 0)
    {
        printf("\n mutex init failed\n");         return 1;
    }
 
 
	allocate_map();
	while(i < 20)
    {
        err = pthread_create(&(tid[i]), NULL, &do_something, (void*)i);
        if (err != 0)
        i++;
		thread_counter++;
		//printf("\nthread %d created\n", i);
    }
 
	while (thread_counter >0)
	{
		sleep(1);
	}
	 pthread_mutex_destroy(&mutex);
}
 
 
 
 
				I2luY2x1ZGUgPHB0aHJlYWQuaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHRpbWUuaD4KCgojZGVmaW5lIFBJRF9NSU4gIAkwCiNkZWZpbmUgUElEX01BWCAJMwoKI2RlZmluZSBOVU1fVEhSRUFEUyAxMDAKI2RlZmluZSBJVEVSQVRJT05TCTEwCiNkZWZpbmUgU0xFRVAJCTUKCgoKCmludCBTOwoKLyogbXV0ZXggbG9jayBmb3IgYWNjZXNzaW5nIHBpZF9tYXAgKi8KcHRocmVhZF9tdXRleF90IG11dGV4OwoKaW50IHBpZF9tYXBbUElEX01BWC1QSURfTUlOKzFdOwppbnQgdGhyZWFkX2NvdW50ZXIgPTA7CgoKaW50IGFsbG9jYXRlX21hcCh2b2lkKTsKaW50IGFsbG9jYXRlX3BpZChpbnQgdGhyZWFkX2lkKTsKdm9pZCByZWxlYXNlX3BpZChpbnQgcGlkKTsKCgoKIC8vIEFsbG9jYXRlcyB0aGUgcGlkIG1hcC4KIAppbnQgYWxsb2NhdGVfbWFwKHZvaWQpIAp7CgkvKmluaXRpbGl6ZSB0byB6ZXJvIGV4cGxpY2l0bHkganVzdCB0byBtYWtlIHN1cmUqLwoJaW50IGk7Cglmb3IgKGkgPTA7aTxQSURfTUFYLVBJRF9NSU4rMTtpKyspCgl7CgkJcGlkX21hcFtpXSA9IDA7CgkJUysrOwoJCQoJfQoJcHJpbnRmKCJtYXAgYWxsb2NhdGVkIVM9JWRcbiIsUyk7CglyZXR1cm4gMTsKfQoKLyoqCiAqIEFsbG9jYXRlcyBhIHBpZAogKi8KaW50IGFsbG9jYXRlX3BpZChpbnQgdF9pZCkKewoJaW50IG5leHRfcGlkOwoJaW50IGksajsKCWludCBlcnI7CgkKCWZvciAoaj0wO2o8UElEX01BWC1QSURfTUlOKzE7aisrKQoJCXsKCQlwcmludGYoIiVkIixwaWRfbWFwW2pdKTsKCQl9CglwcmludGYoIlxuIik7CgkKCQoJcHJpbnRmKCJUaHJlYWQgJWQgdHJ5aW5nIHRvIGxvY2suLi4lZFxuIix0X2lkLHB0aHJlYWRfbXV0ZXhfbG9jaygmbXV0ZXgpKTsKCVMtLTsKCQoJZm9yIChpID0wO2k8UElEX01BWC1QSURfTUlOO2krKykKCQl7CgkJCWlmIChwaWRfbWFwW2ldID09IDApCgkJCQl7CgkJCQkJcGlkX21hcFtpXSA9IDE7CgkJCQkJbmV4dF9waWQ9aTsKCQkJCQlwdGhyZWFkX211dGV4X3VubG9jaygmbXV0ZXgpOwoJCQkJCXJldHVybiBuZXh0X3BpZCtQSURfTUlOOwoJCQkJCQkKCQkJCQoJCQkJCQoJCQkJfQoJCX0KCXJldHVybiAtOTk5OwoJIAp9Ci8qKgogKiBSZWxlYXNlcyBhIHBpZAogKi8Kdm9pZCByZWxlYXNlX3BpZChpbnQgcGlkKQp7CglwaWQgPSBwaWQtUElEX01JTjsKCXBpZF9tYXBbcGlkXSA9IDA7CglTKys7Cn0KCnZvaWQgKmRvX3NvbWV0aGluZyh2b2lkICp0aHJlYWRpZCkKCXsKCQlpbnQgIG15X3BpZDsKCQlsb25nIHRocmVhZF9pZDsKCQlpbnQgaTsKCQlkb3VibGUgcjsKCQl0aHJlYWRfaWQ9IChsb25nKXRocmVhZGlkOwoJCS8vcHJpbnRmKCJcbnRocmVhZCAlZCBsYXVuY2hlZCBkb19zb21ldGhpbmdcbiIsIHRocmVhZF9pZCk7CgkJZm9yIChpPTA7aTwxO2krKykKCQl7CgkJCXIgPSByYW5kKCklNTA7IC8vIDAtNTAKCQkJcj1yLzEwOwoJCQkvL3I9MC4xOwoJCQkvL3ByaW50ZigidGhyZWFkICVkIHRyeWluZyB0byBhbGxvY2F0ZSBQSUQuLi4sIFM9JWRcbiIsdGhyZWFkX2lkLFMpOwoJCQlteV9waWQ9YWxsb2NhdGVfcGlkKHRocmVhZF9pZCk7CgkJCQoJCQlwcmludGYoIlRocmVhZCBudW1iZXIgJWQgZ290IFBJRCAlZCBTPSVkXG4iLCB0aHJlYWRfaWQsIG15X3BpZCxTKTsKCQkJc2xlZXAocik7CgkJCXJlbGVhc2VfcGlkKG15X3BpZCk7CgkJCQoJCQlwcmludGYoIlRocmVhZCBudW1iZXIgJWQgcmVsZWFzZWQgUElEICVkIFM9JWQgXG4iLCB0aHJlYWRfaWQsIG15X3BpZCxTKTsKCQkJCgkJfQoJCQoJCXRocmVhZF9jb3VudGVyLS07CgkJcmV0dXJuOwoJfQoKCQppbnQgbWFpbigpCnsKCWludCBpLGVycjsKCXRpbWVfdCB0OwoJCglwdGhyZWFkX3QgdGlkW05VTV9USFJFQURTXTsKCWlmIChwdGhyZWFkX211dGV4X2luaXQoJm11dGV4LCBOVUxMKSAhPSAwKQogICAgewogICAgICAgIHByaW50ZigiXG4gbXV0ZXggaW5pdCBmYWlsZWRcbiIpOwogICAgICAgIHJldHVybiAxOwogICAgfQoJCgkKCXNyYW5kKCh1bnNpZ25lZCkgdGltZSgmdCkpOwoJYWxsb2NhdGVfbWFwKCk7Cgl3aGlsZShpIDwgMjApCiAgICB7CiAgICAgICAgZXJyID0gcHRocmVhZF9jcmVhdGUoJih0aWRbaV0pLCBOVUxMLCAmZG9fc29tZXRoaW5nLCAodm9pZCopaSk7CiAgICAgICAgaWYgKGVyciAhPSAwKQogICAgICAgICAgICBwcmludGYoIlxuY2FuJ3QgY3JlYXRlIHRocmVhZCA6WyVzXSIsIHN0cmVycm9yKGVycikpOwogICAgICAgIGkrKzsKCQl0aHJlYWRfY291bnRlcisrOwoJCS8vcHJpbnRmKCJcbnRocmVhZCAlZCBjcmVhdGVkXG4iLCBpKTsKICAgIH0KCQoJd2hpbGUgKHRocmVhZF9jb3VudGVyID4wKQoJewoJCXNsZWVwKDEpOwoJfQoJIHB0aHJlYWRfbXV0ZXhfZGVzdHJveSgmbXV0ZXgpOwoJcHJpbnRmKCJET05FIVxuIik7Cn0KCgoK