#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
 
 
#define PID_MIN  	300
#define PID_MAX 	350
 
#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;
int thread_counter =0;
 
 
int allocate_map(void);
int allocate_PID(int thread_id); //not (void) purely for a nicer output, it shows therad id
void release_pid(int pid);
 
 
 
 // Allocates the pid map.
 
int allocate_map(void) 
{
	/*initilize to zero explicitly just to make sure*/
	int i;
		pid_map 
=(int*)malloc((PID_MAX
-PID_MIN
+1)*sizeof(int));		if (pid_map == NULL)
			return -1;
 
		// the structure is a bitmap:
		//0 - available,
		//1 - taken
        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;
 
	if (S<=0)
		return -1; //NOT thread SAFE
 
    pthread_mutex_lock(&mutex);
	while (S<=0)
    {}
 
	for (i =0;i<PID_MAX-PID_MIN+1;i++)
		{
			if (pid_map[i] == 0)
				{
 
                    S--;
                    printf("Thread number %d got PID %d S=%d\n", t_id
, i
+PID_MIN
,S
);                     pid_map[i] = 1;
					next_pid=i;
					pthread_mutex_unlock(&mutex);
					return (next_pid+PID_MIN);
 
 
 
				}
		}
	//for debug purposes:
	//if a thread will pass mutex and S-semaphore
	//but won't find a PID then -999 will be returned
	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<10;i++)
		while(2>1)	
		{
			r=r/10;
 
			sleep(r/100);
			my_pid=allocate_PID(thread_id); //will return PID or "-1" if unsucessfull
			if (my_pid==-1)
				{
					printf("thread %d was NOT able allocate PID\n",thread_id
);	  
				}
			else
				{
					sleep(r);
					release_pid(my_pid);
 
					printf("Thread number %d released PID %d \tPIDs available: %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 < NUM_THREADS)
    {
        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);
}
 
 
 
 
				I2luY2x1ZGUgPHB0aHJlYWQuaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHRpbWUuaD4KCgojZGVmaW5lIFBJRF9NSU4gIAkzMDAKI2RlZmluZSBQSURfTUFYIAkzNTAKCiNkZWZpbmUgTlVNX1RIUkVBRFMgMTAwCiNkZWZpbmUgSVRFUkFUSU9OUwkxMAojZGVmaW5lIFNMRUVQCQk1CgoKCgppbnQgUzsKCi8qIG11dGV4IGxvY2sgZm9yIGFjY2Vzc2luZyBwaWRfbWFwICovCnB0aHJlYWRfbXV0ZXhfdCBtdXRleDsKCmludCogcGlkX21hcDsKaW50IHRocmVhZF9jb3VudGVyID0wOwoKCmludCBhbGxvY2F0ZV9tYXAodm9pZCk7CmludCBhbGxvY2F0ZV9QSUQoaW50IHRocmVhZF9pZCk7IC8vbm90ICh2b2lkKSBwdXJlbHkgZm9yIGEgbmljZXIgb3V0cHV0LCBpdCBzaG93cyB0aGVyYWQgaWQKdm9pZCByZWxlYXNlX3BpZChpbnQgcGlkKTsKCgoKIC8vIEFsbG9jYXRlcyB0aGUgcGlkIG1hcC4KIAppbnQgYWxsb2NhdGVfbWFwKHZvaWQpIAp7CgkvKmluaXRpbGl6ZSB0byB6ZXJvIGV4cGxpY2l0bHkganVzdCB0byBtYWtlIHN1cmUqLwoJaW50IGk7CgkJcGlkX21hcCA9KGludCopbWFsbG9jKChQSURfTUFYLVBJRF9NSU4rMSkqc2l6ZW9mKGludCkpOwoJCWlmIChwaWRfbWFwID09IE5VTEwpCgkJCXJldHVybiAtMTsKCQkKCQkvLyB0aGUgc3RydWN0dXJlIGlzIGEgYml0bWFwOgoJCS8vMCAtIGF2YWlsYWJsZSwKCQkvLzEgLSB0YWtlbgogICAgICAgIGZvciAoaSA9MDtpPFBJRF9NQVgtUElEX01JTisxO2krKykKICAgICAgICB7CiAgICAgICAgICAgIHBpZF9tYXBbaV0gPSAwOwogICAgICAgICAgICBTKys7CgkJCiAgICAgICAgfQogICAgICAgIHByaW50ZigibWFwIGFsbG9jYXRlZCFTPSVkXG4iLFMpOwogICAgICAgIHJldHVybiAxOwogICAgCn0KCi8qKgogKiBBbGxvY2F0ZXMgYSBwaWQKICovCmludCBhbGxvY2F0ZV9QSUQoaW50IHRfaWQpCnsKCWludCBuZXh0X3BpZDsKCWludCBpLGo7CglpbnQgZXJyOwoJCglpZiAoUzw9MCkKCQlyZXR1cm4gLTE7IC8vTk9UIHRocmVhZCBTQUZFCgkKICAgIHB0aHJlYWRfbXV0ZXhfbG9jaygmbXV0ZXgpOwoJd2hpbGUgKFM8PTApCiAgICB7fQoJCglmb3IgKGkgPTA7aTxQSURfTUFYLVBJRF9NSU4rMTtpKyspCgkJewoJCQlpZiAocGlkX21hcFtpXSA9PSAwKQoJCQkJewogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIFMtLTsKICAgICAgICAgICAgICAgICAgICBwcmludGYoIlRocmVhZCBudW1iZXIgJWQgZ290IFBJRCAlZCBTPSVkXG4iLCB0X2lkLCBpK1BJRF9NSU4sUyk7CiAgICAgICAgICAgICAgICAgICAgcGlkX21hcFtpXSA9IDE7CgkJCQkJbmV4dF9waWQ9aTsKCQkJCQlwdGhyZWFkX211dGV4X3VubG9jaygmbXV0ZXgpOwoJCQkJCXJldHVybiAobmV4dF9waWQrUElEX01JTik7CgkJCQkJCQoJCQkJCgkJCQkJCgkJCQl9CgkJfQoJLy9mb3IgZGVidWcgcHVycG9zZXM6CgkvL2lmIGEgdGhyZWFkIHdpbGwgcGFzcyBtdXRleCBhbmQgUy1zZW1hcGhvcmUKCS8vYnV0IHdvbid0IGZpbmQgYSBQSUQgdGhlbiAtOTk5IHdpbGwgYmUgcmV0dXJuZWQKCXJldHVybiAtOTk5OwoJIAp9Ci8qKgogKiBSZWxlYXNlcyBhIHBpZAogKi8Kdm9pZCByZWxlYXNlX3BpZChpbnQgcGlkKQp7CglwaWQgPSBwaWQtUElEX01JTjsKCXBpZF9tYXBbcGlkXSA9IDA7CglTKys7Cn0KCnZvaWQgKmRvX3NvbWV0aGluZyh2b2lkICp0aHJlYWRpZCkKCXsKCQlpbnQgIG15X3BpZDsKCQlsb25nIHRocmVhZF9pZDsKCQlpbnQgaTsKCQlkb3VibGUgcjsKCQl0aHJlYWRfaWQ9IChsb25nKXRocmVhZGlkOwoJCS8vcHJpbnRmKCJcbnRocmVhZCAlZCBsYXVuY2hlZCBkb19zb21ldGhpbmdcbiIsIHRocmVhZF9pZCk7CgkJCgkJCgkJCgkJLy9mb3IgKGk9MDtpPDEwO2krKykKCQl3aGlsZSgyPjEpCQoJCXsKCQkJciA9IHJhbmQoKSU1MDsgLy8gMC01MAoJCQlyPXIvMTA7CgkJCQoJCQlzbGVlcChyLzEwMCk7CgkJCW15X3BpZD1hbGxvY2F0ZV9QSUQodGhyZWFkX2lkKTsgLy93aWxsIHJldHVybiBQSUQgb3IgIi0xIiBpZiB1bnN1Y2Vzc2Z1bGwKCQkJaWYgKG15X3BpZD09LTEpCgkJCQl7CgkJCQkJcHJpbnRmKCJ0aHJlYWQgJWQgd2FzIE5PVCBhYmxlIGFsbG9jYXRlIFBJRFxuIix0aHJlYWRfaWQpOwkKCQkJCQoJCQkJfQoJCQllbHNlCgkJCQl7CgkJCQkJc2xlZXAocik7CgkJCQkJcmVsZWFzZV9waWQobXlfcGlkKTsKCQkJCQoJCQkJCXByaW50ZigiVGhyZWFkIG51bWJlciAlZCByZWxlYXNlZCBQSUQgJWQgXHRQSURzIGF2YWlsYWJsZTogJWQgXG4iLCB0aHJlYWRfaWQsIG15X3BpZCxTKTsKCQkJCQl0aHJlYWRfY291bnRlci0tOwoJCQkJCXJldHVybjsKCQkJCX0KCQl9CgkJCgkJCgl9CgoJCmludCBtYWluKCkKewoJaW50IGksZXJyOwoJdGltZV90IHQ7CgkKCXB0aHJlYWRfdCB0aWRbTlVNX1RIUkVBRFNdOwoJaWYgKHB0aHJlYWRfbXV0ZXhfaW5pdCgmbXV0ZXgsIE5VTEwpICE9IDApCiAgICB7CiAgICAgICAgcHJpbnRmKCJcbiBtdXRleCBpbml0IGZhaWxlZFxuIik7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CgkKCQoJc3JhbmQoKHVuc2lnbmVkKSB0aW1lKCZ0KSk7CglhbGxvY2F0ZV9tYXAoKTsKCXdoaWxlKGkgPCBOVU1fVEhSRUFEUykKICAgIHsKICAgICAgICBlcnIgPSBwdGhyZWFkX2NyZWF0ZSgmKHRpZFtpXSksIE5VTEwsICZkb19zb21ldGhpbmcsICh2b2lkKilpKTsKICAgICAgICBpZiAoZXJyICE9IDApCiAgICAgICAgICAgIHByaW50ZigiXG5jYW4ndCBjcmVhdGUgdGhyZWFkIDpbJXNdIiwgc3RyZXJyb3IoZXJyKSk7CiAgICAgICAgaSsrOwoJCXRocmVhZF9jb3VudGVyKys7CgkJLy9wcmludGYoIlxudGhyZWFkICVkIGNyZWF0ZWRcbiIsIGkpOwogICAgfQoJCgl3aGlsZSAodGhyZWFkX2NvdW50ZXIgPjApCgl7CgkJc2xlZXAoMSk7Cgl9CgkgcHRocmVhZF9tdXRleF9kZXN0cm95KCZtdXRleCk7CglwcmludGYoIioqKkRPTkUhKioqXG4iKTsKfQoKCgo=