So I've got this great code for a C example of a deadlock by Ali Hasan Ahmed Khan previously. I was just thinking about converting it to a parent-child process, so somehow making funcA the parent, then forking funcB. When I used the fork command, I was met with an error in main, saying funcB is non existent. Can this be converted? The full code is:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/sem.h>
#define PERMS 0660
int semId;
int initSem(int semId, int semNum, int initValue) {
return semctl(semId, semNum, SETVAL, initValue);
}
// Try to take a resource, wait if not available
int P(int semId, int semNum) {
struct sembuf operationList[1];
operationList[0].sem_num = semNum;
operationList[0].sem_op = -1;
operationList[0].sem_flg = 0;
return semop(semId, operationList, 1);
}
// Release a resource
int V(int semId, int semNum) {
struct sembuf operationList[1];
operationList[0].sem_num = semNum;
operationList[0].sem_op = 1;
operationList[0].sem_flg = 0;
return semop(semId, operationList, 1);
}
void* funcA(void* nothing) {
printf("Thread A try to lock 0...\n");
P(semId, 0); // Take resource/semaphore 0 of semID
printf("Thread A locked 0.\n");
usleep(50*1000); // Wait 50 ms
printf("Thread A try to lock 1...\n");
P(semId, 1); // Take resource/semaphore 1 of semID
printf("Thread A locked 1.\n");
V(semId, 0); // Release resource/semaphore 0 of semID
V(semId, 1); // Release resource/semaphore 1 of semID
return NULL;
}
void* funcB(void* nothing) {
printf("Thread B try to lock 1...\n");
P(semId, 1);
printf("Thread B locked 1.\n");
usleep(5*1000);
printf("Thread B try to lock 0...\n");
P(semId, 0);
printf("Thread B locked 0.\n");
V(semId, 0);
V(semId, 1);
return NULL;
}
int main(int argc, char* argv[]) {
int i;
// ftok generates a key based on the program name and a char value
semId = semget(ftok(argv[0], 'A'), 2, IPC_CREAT | PERMS);
initSem(semId, 0, 1);
initSem(semId, 1, 1);
pthread_t thread[2];
pthread_create(&thread[0], NULL, funcA, NULL);
pthread_create(&thread[1], NULL, funcB, NULL);
for (i = 0 ; i < 2 ; i++) {
pthread_join(thread[i], NULL);
}
printf("This is not printed in case of deadlock\n");
semctl(semId, 0, IPC_RMID, 0);
semctl(semId, 1, IPC_RMID, 0);
return 0;
}
Related
I have coded little program that uses shared memory that sends bytes around basicly.
The problem I have is, I think, that I'm getting stuck in the child process (it prints Process 2: 5000 and then nothing).
Can anyone help me? I'd really appreciate it!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main() {
int sem_id;
int shm_id;
key_t key = ftok("shared_memory", 1); // Create key shared memory
key_t keytwo = ftok("semaphore", 1); // Create key semaphore
shm_id = shmget(key, sizeof(int), IPC_CREAT | 0666); // Create shared memory
sem_id = semget(keytwo, 1, IPC_CREAT | 0666); // Create Semaphore
if((shm_id = shmget(key, sizeof(int), IPC_CREAT | 0666)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Shared memory created with id: %d \n", shm_id);
}
if((sem_id = semget(keytwo, 1, IPC_CREAT | 0666)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Sephamore created with id: %d \n", shm_id);
}
struct sembuf sem_lock = {0, -1, 0}; // Struct for semop to lock
struct sembuf sem_unlock = {0, 1, 0}; // Struct for semop to unlock
char *data = (char *)shmat(shm_id, NULL, 0); // Connect Shared-Memorys to Process
pid_t pid;
semctl(sem_id, 0, SETVAL, 1); //initialize the semaphore with value 1
if((semctl(sem_id, 0, SETVAL, 1)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Sephamore initialized \n");
}
pid = fork();
if(pid < 0){
printf("Error");
return 1;
}
int p = 1;
int c = 1;
//16777216 = 1024 * 16384
char *message = (char *) malloc(16777216);
char *read = (char *) malloc(16777216);
for (int KiB = 1; KiB <= 16384; KiB *= 2) {
int bytes = KiB * 1024;
for(int i = 0; i < 1000; i++){
if (pid == 0) {
// Process 2:
semop(sem_id, &sem_lock, 1);
memcpy(read, data, bytes); //"read" data
//printf("%s \n", read) //print to check whether read worked
semop(sem_id, &sem_unlock, 1);
//print to check race condition
printf("Process 2 print: %d \n", p);
p++;
} else {
// Process 1:
for (int i = 0; i < bytes; ++i) {
message[i] = 'a';
}
semop(sem_id, &sem_lock, 1);
printf("%d", sem_id);
memcpy(data, message, bytes);
semop(sem_id, &sem_unlock, 1);
//print to check race condition
printf("Process 1 print: %d \n", c);
c++;
wait(NULL);
}
}
}
shmdt(data); // Remove shared-memory from process
shmctl(shm_id, IPC_RMID, NULL); // Delete shared memory
semctl(sem_id, 0, IPC_RMID); // Delete semaphore
return 0;
}
I was expecting the processes to alternate.
I have tried:
Place locks differently, Add locks, Remove locks, Remove unlocks, sleep(1).
I am not saying this is the reason for the failure, but you are not testing any return codes from these functions. Always test returns, especially if you are seeing problems and / or are new to calls
taking semctl as an example. looking here https://man7.org/linux/man-pages/man2/semctl.2.html you see that it returns a value indicating the result
so here
semctl(sem_id, 0, SETVAL, 1); //initialize the semaphore with value 1
you should do
if(semctl(sem_id, 0, SETVAL, 1) == -1){ // -1 indicates error
perror("semctl");
exit(1);
}
I'm trying to implement producer-consumer problem in C using processes and System V IPC and I'm stuck on one thing. This is early version of my code (without implementing queue operations or even producer and consumer executing in loop) that I was using to learn and test how semaphores work:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <time.h>
#include "sem.h"
#include "shm.h"
#define BUFFER_SIZE 9
int full;
int empty;
int mutex;
struct buff {
int queue[BUFFER_SIZE];
} *buffer;
void producer();
void consumer();
int main() {
int parent_pid, pid, i;
parent_pid = getpid();
int shmid = allocate_shared_memory(sizeof(*buffer));
buffer = (struct buff *) attach_shared_memory(shmid);
for (i = 0; i < BUFFER_SIZE; i++) {
buffer->queue[i] = 0;
}
full = sem_allocate();
empty = sem_allocate();
mutex = sem_allocate();
printf("Full %d\n", full);
printf("Empty %d\n", empty);
printf("Mutex %d\n", mutex);
sem_init(full, 0);
sem_init(empty, BUFFER_SIZE);
sem_init(mutex, 1);
printf("Full value %d\n", sem_get_val(full));
printf("Empty value %d\n", sem_get_val(empty));
printf("Mutex value %d\n", sem_get_val(mutex));
srand(time(0));
pid = fork();
if (!pid) {
printf("Producer here: %d\n", getpid());
producer();
printf("Full value after prod() %d\n", sem_get_val(full));
return 0;
} else printf("Created new producent: %d\n", pid);
sleep(1);
pid = fork();
if (!pid) {
printf("Consumer here: %d\n", getpid());
printf("Full value before cons() %d\n", sem_get_val(full)); //here I always get 0
consumer();
return 0;
} else printf("Created new consumer: %d\n", pid);
while (1)
{
int status;
pid_t done = wait(&status);
if (done == -1)
{
if (errno == ECHILD) break; // no more child processes
}
else
{
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
exit(1);
}
}
}
if (getpid() == parent_pid) {
sem_deallocate(full);
sem_deallocate(empty);
sem_deallocate(mutex);
}
}
void producer() {
sem_wait(empty);
sem_wait(mutex);
printf("Producer is producing!\n");
buffer->queue[0]=0;
sem_post(mutex);
sem_post(full);
}
void consumer() {
sem_wait(full);
sem_wait(mutex);
printf("Consumer is consuming!\n");
sem_post(mutex);
sem_post(empty);
}
int sem_allocate() {
return semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
}
void sem_deallocate(int semid) {
if (semctl(semid, 0, IPC_RMID, NULL) == -1)
{
perror("Error releasing semaphore!\n");
exit(EXIT_FAILURE);
}
}
int sem_init(int semid, int value) {
union semun arg;
arg.val = value;
if (semctl(semid, 0, SETVAL, arg) == -1) {
perror("semctl");
return -1;
}else return 1;
}
int sem_wait(int semid) {
printf("Someone is waiting %d\n", semid);
struct sembuf sem = { 0, -1, SEM_UNDO };
return semop(semid, &sem, 1);
}
int sem_post(int semid) {
printf("Someone is posting %d\n", semid);
struct sembuf sem = { 0, 1, SEM_UNDO };
return semop(semid, &sem, 1);
}
int sem_get_val(int semid) {
return semctl(semid, 0, GETVAL, 0);
}
int allocate_shared_memory(int size) {
return shmget(IPC_PRIVATE, size, IPC_CREAT | SHM_W | SHM_R);
}
void deallocate_shared_memory(const void* addr, int shmid) {
shmctl(shmid, IPC_RMID, 0);
}
void* attach_shared_memory(int shmid) {
return shmat(shmid, NULL, 0);
}
sem.h:
#include <sys/types.h>
#include <errno.h>
union semun {
int val;
struct semid_ds *buf;
ushort* array;
};
int sem_post(int);
int sem_wait(int);
int sem_allocate();
void sem_deallocate(int);
int sem_init(int, int);
int sem_get_val(int);
shm.h:
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int allocate_shared_memory(int size);
void deallocate_shared_memory(const void* addr, int shmid);
void* attach_shared_memory(int shmid);
Why before executing consumer function value of full semaphore is 0? Even if right after producer finishes his job the value is 1...
I'm new to this kind of topics so maybe there is an obvious explenation of the situation, but I have no idea what can I do and hope you can help me.
You initialize the "full" semaphore to zero. Your "child" producer, prior to exiting calls your sem_post() function, which calls semop() with a SEM_UNDO argument.
int sem_post(int semid) {
printf("Someone is posting %d\n", semid);
struct sembuf sem = { 0, 1, SEM_UNDO };
return semop(semid, &sem, 1);
}
The Ubuntu Linux man page for semop says the following about SEM_UNDO:
... If an operation specifies SEM_UNDO, it will be automatically
undone when the process terminates.
This means, "producer" increments "full" prior to exiting, then after it exits the system "undoes" the increment (i.e. it decrements "full") setting it back to zero.
So,for the purposes of the "full" semaphore, you should NOT specify SEM_UNDO.
I am trying to add the variable bank into shared memory to explore race conditions and process synchronization using semaphores. When I setup the variable in shared memory my program gives me segmentation fault:11. Can someone explain what I am doing wrong here and how I can go about fixing this? Thanks!
RACE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <semaphore.h>
int shmid;
int shmkey = 585858;
sem_t mutex; // semaphore global variable
struct Bank {
int balance[2];
};
struct Bank *bank;
// routine for thread execution
void* MakeTransactions() {
int i, j, tmp1, tmp2, rint;
double dummy;
// wait on semaphore
//sem_wait(&mutex);
for (i=0; i < 100; i++) {
rint = (rand()%30)-15;
if (((tmp1=bank->balance[0])+rint) >=0 &&
((tmp2=bank->balance[1])-rint)>=0) {
//sem_wait(&mutex);
bank->balance[0] = tmp1 + rint;
//sem_post(&mutex);
for (j=0; j < rint*100; j++) {
dummy=2.345*8.765/1.234; // spend time on purpose
}
//sem_wait(&mutex);
bank->balance[1] = tmp2 - rint;
//sem_post(&mutex);
}
}
// increment value of semaphore
//sem_post(&mutex);
return NULL;
}
int main(int argc, char **argv) {
int i;
void* voidptr = NULL;
// initialize semaphore
sem_init(&mutex, 0, 1);
// shared memory
//bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// create shared memory
shmid = shmget(shmkey, 1024, IPC_CREAT);
// attach to shared memory
bank = shmat(shmid, NULL, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
pid_t pid;
srand(getpid());
printf("\nInit balances A:%d + B:%d ==> %d!",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
pid=fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid == 0) {
printf("\nChild computing ...");
MakeTransactions();
printf("\nChild process complete");
printf("\nLet's check the balances A:%d + B:%d ==> %d ?= 200",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
else {
printf("\nParent computing...\n");
MakeTransactions();
wait(NULL);
printf("\nParent process complete\n");
printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
sem_destroy(&mutex);
// deattach shared memory pointer
shmdt(&bank,NULL);
//munmap(bank, sizeof(struct Bank));
return 0;
}
Okay the reason it gives you a segfault is because you're probably running this program as an unprivileged user. shmat requires privileges. If you are running it under linux you can do this:
sudo setcap cap_ipc_owner=ep ./myprog
to enable it to call shmat etc.
and then run it.
You would've found out about this if you had added a bit of error handling:
shmid = shmget(shmkey, 1024, IPC_CREAT);
if (shmid == -1 ) {
perror("shmget");
exit(errno);
}
// attach to shared memory
bank = shmat(shmid, NULL, 0);
if (bank == (void *)-1) {
perror("bank");
exit(errno);
}
I am trying to understand the concept of counting semaphore through an example. But I want to implement this using SysV in Linux.
I am familiar with theoretical part of binary semaphore and counting semaphore.
I have referred this link.
Conceptually, semaphores are used as a signaling mechanism from one process to another, so I was trying to write a simple program.
In the below program, I want thread_1 to wait till it doesn't get a signal from thread_2 and similarly thread_2 should wait till it doesn't get a signal from thread_3.
So that the output should be something like this:
Hello From thread 3
Hello from thread 2
Hello from thread 1
I know it can be achieved using pthread_join() properly but I want to achieve it using semaphores.
Code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
struct sembuf sops[3];
void thread_1(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = 0;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 3");
else
printf("Hello From thread 1\n");
}
void thread_2(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 2");
else
printf("Hello from thread 2\n");
}
void thread_3(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 3");
else
printf("Hello from thread 3\n");
}
int main(void)
{
void (*funct[]) = {thread_1, thread_2, thread_3};
key_t semkey;
char i;
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}arg;
pthread_t thread_id[3];
semkey = ftok("/tmp", 'a');
if(semkey < 0)
perror("Cannot Create Semaphore Key");
else
{
sem_id = semget(semkey, 1, (IPC_CREAT|IPC_EXCL|0666));
if(sem_id < 0)
perror("Cannot create semaphore\n");
else
{
arg.val = 3;
if (semctl(sem_id, 0, SETVAL, arg) == -1) {
perror("semctl");
exit(1);
}
}
}
for(i = 0; i < 3; i++)
{
if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
perror("Cannot Create thread\n");
}
for(i = 0; i < 3; i++)
pthread_join(thread_id[i], NULL);
if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
perror("semctl");
return 0;
}
Do I have to use more than one semaphore set to achieve what I am trying to do?
You need two mutexes / semaphores with count 1.
Assuming your threads are called t0,t1,t2 and your semaphores sem0 and sem1, then t0 runs freely and increments sem0, t1 waits on sem0 and increments sem1, and t2 waits on sem1.
Here's a complete draft without error checking:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
static int sem0, sem1;
#define POST1(Sem) semop(Sem, &(struct sembuf){0,1,0}, 1)
#define WAIT1(Sem) semop(Sem, &(struct sembuf){0,-1,0}, 1)
static void* t0(void *unused) { puts("hello from t0"); POST1(sem0); return 0; }
static void* t1(void *unused) { WAIT1(sem0); puts("hello from t1"); POST1(sem1); return 0; }
static void* t2(void *unused) { WAIT1(sem1); puts("hello from t2"); return 0; }
int main(void)
{
key_t sem0_k, sem1_k;
sem0_k = ftok("/tmp", '0');
sem1_k = ftok("/tmp", '1');
sem0 = semget(sem0_k, 1, (IPC_CREAT|IPC_EXCL|0666));
sem1 = semget(sem1_k, 1, (IPC_CREAT|IPC_EXCL|0666));
pthread_t tids[3];
pthread_create(tids+2, NULL, t2, NULL);
sleep(1);
pthread_create(tids+1, NULL, t1, NULL);
sleep(1);
pthread_create(tids+0, NULL, t0, NULL);
for(int i = 0; i < 3; i++)
pthread_join(tids[i], NULL);
semctl(sem0, 0, IPC_RMID, NULL);
semctl(sem1, 0, IPC_RMID, NULL);
return 0;
}
I'm running the threads in reverse order and with 1 second waits in between t0 and t1, and t1 and t2 to show the semaphores do the job of ordering the threads from t0 to t2.
#PSkocik, based on your answer, I modified my code to use a set of two semaphores. Here is the code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
struct sembuf sops;
void thread_1(void)
{
/*Wait on Set1 of Semaphore*/
sops.sem_num = 1;
sops.sem_op = -1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Wait In thread 3");
else
printf("Hello From thread 1\n");
}
void thread_2(void)
{
/*Wait on Set0 of Semaphore*/
sops.sem_num = 0;
sops.sem_op = -1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Wait In thread 2");
else
printf("Hello from thread 2\n");
/*Post on Set1 of Semaphore*/
sops.sem_num = 1;
sops.sem_op = 1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Post In thread 2");
}
void thread_3(void)
{
printf("Hello from thread 3\n");
/*Post operation on Set0 of semaphore*/
sops.sem_num = 0;
sops.sem_op = 1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop In thread 3");
else
{ ; }
}
int main(void)
{
void (*funct[]) = {thread_1, thread_2, thread_3};
key_t semkey;
char i;
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}arg;
pthread_t thread_id[3];
semkey = ftok("/tmp", 'a');
if(semkey < 0)
perror("Cannot Create Semaphore Key");
else
{
sem_id = semget(semkey, 2, (IPC_CREAT|IPC_EXCL|0666));
if(sem_id < 0)
perror("Cannot create semaphore\n");
else
{
/*arg.val = 3;
if (semctl(sem_id, 0, SETVAL, arg) == -1) {
perror("semctl");
exit(1);
}*/
}
}
for(i = 0; i < 3; i++)
{
if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
perror("Cannot Create thread\n");
}
for(i = 0; i < 3; i++)
pthread_join(thread_id[i], NULL);
if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
perror("semctl");
return 0;
}
BTW, thanks a bunch for your explanation.
I want to create two thread which output interleave like below
Thread1:1=>Ping!
Thread2:2=>Pong!
Thread1:3=>Ping!
Thread1:4=>Ping!
Thread2:5=>Pong!
Thread2:6=>Pong!
Thread1:7=>Ping!
Thread2:8=>Pong!
Thread1:9=>Ping!
..........
until 50
and my code is below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i){
//create thread
res1 = pthread_create(&thread1, NULL, increment1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread1, NULL);
res2 = pthread_create(&thread2, NULL, increment2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread2, NULL);
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread1:%d\nPing!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
void* increment2(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread2:%d\nPong!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
But I think that what I do isn't using two thread in parallel and is wrong, what I use is sequential alternative executing two thread and it isn't not in parallel.(By using pthread_join, thread2 will execute after thread1 finish).
I try to using semaphore it seem that it cannot assure the thread execution order.
What I want to ask is
1.how to using semaphore to assure the two thread order?
2.how to pause the thread and resume it? I think that I do is create new two pthread in a loop cycle.
Thank in advance.
Add a second semaphore and initialize it to zero so that thread1 is forced to first. Then increment1 and increment2 keep signally that it is the other threads turn to go. You had some minor hangups with where joined things that you can figure out.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;
int main()
{
pthread_t thread[2];
int res = 0;
int number = 0;
int i = 0;
if (sem_init(&sem1, 0, 1) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem2, 0, 0) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i)
{
res = pthread_create(&thread[0], NULL, increment1, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
res = pthread_create(&thread[1], NULL, increment2, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
for (int j = 0; j < 2; ++j)
{
pthread_join(thread[j], NULL);
}
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg)
{
sem_wait(&sem1);
count ++;
printf("Thread1:%d Ping!\n", count);
fsync(fileno(stdout));
sem_post(&sem2);
}
void* increment2(void* arg)
{
sem_wait(&sem2);
count ++;
printf("Thread2:%d Pong!\n", count);
fsync(fileno(stdout));
sem_post(&sem1);
}
Thank for you guys, I have modified it and it seems fine.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&c_sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_1, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_2, 0, 0) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
//create thread
res1 = pthread_create(&thread1, NULL, increment_1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
res2 = pthread_create(&thread2, NULL, increment_2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) {
while(1){
sem_wait(&sem_1);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_2);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread1:%d->Ping!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_2);
}
}
void* increment_2(void* arg) {
while(1){
sem_wait(&sem_2);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_1);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread2:%d->Pong!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_1);
}
}