LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-26-2012, 03:06 PM   #1
khmix
LQ Newbie
 
Registered: May 2012
Posts: 2

Rep: Reputation: Disabled
help in dinner philosophers by semaphores


Write a program using c language calls to Linux system to resolve the issue using the semaphores dinner philosophers to solve the problem of synchronization routines in the Linux system.
Orders, call:
fork (), getpid (), semget (), semop (), semctl ()

Dinner philosophers question states:
Five philosophers sit around a table in the ring, and by 4 chairs in front of each dish does not end with its content, and there is a fork between each tow plates, that is in front of each philosopher tow forks: one on his right and the other on his left.
Philosopher spends his life in thinking and eating from a bowl, and to be able to eat need to eat tow forks to be able to eat. After the completion of a meal, clean the philosopher tow forks to their place and ready for use again.

Write a program to:

Resolve the issue for 5 philosophers and five forks 4 chairs.
semaphores used, provided that the request by the philosopher sitting fork and eat.
Type the report describes the solution algorithm and its work program.



I wrote all my experience by semaphores but I could not form the full solution by virtue of your experience, you can:
<Modify the file with the following code to verify the requests in the top>

Code:

#include<errno.h>

#include<math.h>

#include<signal.h>

#include<stdio.h>

#include<stdlib.h>


#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

#include<sys/time.h>


#define FALSE 0

#define TRUE 1

#define NPHIL 4 
#define NCHOPSTICKS NPHIL 

#define AVG_THINK 2.5 

#define AVG_EAT 1.5 
#define DURATION 30 



typedef union semun{

int val; 
struct semid_ds *buf;

ushort *array;

}SEM_UNION;






static int alarm_flag=FALSE;



/*------print error mesage and terminate a process------*/


void error(const char *msg)
{
fflush(stdout);

printf( "%s %d %s\n", msg ,errno,strerror(errno));

exit(0);
}

/*******signal the semaphore*******/



void my_signal(int s)
{

int status;


struct sembuf sb;
sb.sem_num=0;
sb.sem_op=1;
sb.sem_flg=SEM_UNDO;
status=semop(s,&sb,1);//s=semid
if(status<0)
{ error("In my wait,semaphore failed");}
}


/********wait on semaphore*******/
void my_wait(int s)
{
int status;
struct sembuf sb;
sb.sem_num=0;
sb.sem_op=-1;//wait1
sb.sem_flg=SEM_UNDO;

status=semop(s,&sb,1);
if(status<0)
{ error("In my wait,semaphore failed");}
}


/********think *******/
void think(int phil)
{
int duration=drand48()*1000000.0*AVG_THINK;
printf("phil %d (proc %d) thinking %d microseconds\n",phil,getpid(), duration);
usleep(duration);
}

void eat(int phil)
{
int duration=drand48()*1000000.0*AVG_EAT;
printf("phil %d (proc %d) eating %d microseconds\n",phil,getpid(), duration);
usleep(duration);
}


/*****timer*****/

void alarm_handler(sig,code,scp)

int sig;

int code;

struct sigcontext *scp;

{

alarm_flag=TRUE;

}



void set_sig_handler()

{
struct sigaction act;
act.sa_handler=alarm_handler;

#if defined_FreeBSD_
act.sa_mask=0;


#endif
act.sa_flags=SA_RESTART|SA_RESETHAND;

sigaction(SIGUSR1, &act,(struct sigaction *) NULL);

}




/******creat process*********/


int create_philososphers(const int n,int child[])
{ 
int i,status;
for (i=0;i<n;++i)
{

child[i]=0;

}

printf("creating %d philosophers\n",n);


for(i=0;i<n;++i)

{

status=fork();
if(status<0)

{
error("failed to creat philosopher \n");}

else if(status==0)
{return i-1;
}
else{ child[i-1]=status;} 
}
return -1;
}



/**********Main program*********/

int main( int argc,char *argv[])
{
int child[NPHIL],
chopstick[NCHOPSTICKS],i,status, philosopher_id=0 , left,right;
SEM_UNION arg;
key_t k;
for(i=0;i<=NCHOPSTICKS;++i)
{
k=ftok(argv[0],i);
printf("\n",argv[0],k);
chopstick[i]=semget(k,1,IPC_CREAT); 
printf("chopstick[%d] is %d\n",i,chopstick[i]);



if(chopstick[i]<0)

{error("bad sem creat");
}



arg.val=1;
status=semctl(chopstick[i],0,SETVAL,arg);
if(status<0)
{error("couldnt itinalize sem counter to 1");}
}

/*********creat semaphores******/

philosopher_id=create_philososphers(NPHIL,child);

if(philosopher_id==-1)
{
sleep(DURATION);
for(i=0;i<NPHIL;++i)
{
kill(child[i],SIGUSR1);
}
for(i=0;i<NPHIL;++i)
{
status=wait((int *)0);
if(status<0)
{
error("wait erorr detected");
}
}
for(i=0;i<NCHOPSTICKS;i++)
{
status=semctl(chopstick[i],0,IPC_RMID,0);
if(status<0)
{error("bad remove sem");}
}
}
else
{
left=philosopher_id;
right=(philosopher_id +1)%NPHIL;

set_sig_handler();
while(!alarm_flag)
{
think(philosopher_id);
if(philosopher_id & 0x1)
{
my_wait(chopstick[left]);
printf("phil %d picked up left chopstick %d\n",philosopher_id,getpid(),left);
my_wait(chopstick[right]);
printf("phil %d picked up right chopstick %d\n",philosopher_id,getpid(),right);
}
else
{
my_wait(chopstick[right]);
printf("phil %d picked up right chopstick %d\n",philosopher_id,getpid(),right);
my_wait(chopstick[left]);
printf("phil %d picked up left chopstick %d\n",philosopher_id,getpid(),left);
}

eat(philosopher_id);
if(philosopher_id & 0x1)
{
my_signal(chopstick[left]);
printf("phil %d put down left chopstick %d\n",philosopher_id,getpid(),left);
my_signal(chopstick[right]);
printf("phil %d put down right chopstick %d\n",philosopher_id,getpid(),right);
}
else
{
my_signal(chopstick[right]);
printf("phil %d put down right chopstick %d\n",philosopher_id,getpid(),right);
my_signal(chopstick[left]);
printf("phil %d put down left chopstick %d\n",philosopher_id,getpid(),left);
}
}
}
}
 
Old 05-26-2012, 05:10 PM   #2
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985
Per the LQ Rules, please do not post homework assignments verbatim. We're happy to assist if you have specific questions or have hit a stumbling point, however. Let us know what you've already tried and what references you have used (including class notes, books, and Google searches) and we'll do our best to help. Also, keep in mind that your instructor might also be an LQ member.
 
Old 05-27-2012, 01:50 AM   #3
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Furthermore, the exercise is wrong. The semop() is buggy on kernels 2.6.0 to 2.6.10; sometimes the process is not woken up even when the semaphore becomes zero. Requiring the exercise to be written using known buggy interfaces when a reliable alternative exists is just stupid. You cannot even use semop() safely in a signal handler; see man 7 signal, Async-signal-safe functions. (The only semaphore/mutex/rwlock operation allowed in signal handlers is sem_post(), which is a POSIX semaphore function.)

POSIX semaphores using sem_init() et al. work just fine in Linux, and have saner semantics (no SEM_UNDO, for one). Just remember to link against pthread or rt library. For semaphores shared between processes, just put them in a shared memory segment. (You can use mmap(), shmget(), or shm_open(), for example, to obtain a chunk of shared memory.)
 
Old 05-27-2012, 03:17 AM   #4
khmix
LQ Newbie
 
Registered: May 2012
Posts: 2

Original Poster
Rep: Reputation: Disabled
first thanksssssssss

1- Are any of you teach me how to set up procedural and Free Semaphore these procedural controls specifically programmatically. I know the consequences of writing smaphore and routines, but I do not know the link between procedural and smaphore programmatically.

2 - I understand that if there is a procedural and procedural b and we want to make the instruction before the instruction is working a1 b1 b1 get ahead of the instruction
After the instruction sem.wait a1 sem.signal put this in theory, but how this is done programmatically??????

3 - What is the interpretation of the line (provided that the request by the philosopher sitting fork and eating)
Do you sit or philosopher is procedural and thus how Semaphore is represented within the program?? Likewise, request fork and eating.
Briefly how we express this line programmatically
 
Old 05-28-2012, 01:12 AM   #5
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
I'll refer to the POSIX semaphore functions (sem_*()) in this post, but you should be able to use the semop() just as well.

The situation is as follows, withbeing a philosopher, being a plate, and Ѱ being a fork:
Code:
     ┌───☺───┐
     │ Ѱ ◦ Ѱ │
     ☺ ◦   ◦ ☺
     │ Ѱ ◦ Ѱ │
     └───☺───┘
Each philosopher has their own seat and plate, so there is no quarrel about those; each philosopher+seat+plate corresponds to a thread or process. However, they must share the forks, since each philosopher needs two forks to eat.

Because each fork can only be held by one philosopher at a time, access to the forks must be restricted/protected using a semaphore. (A mutex would work just as well, however.)

If we name the philosophers a, b, c, and d, and number the forks 1, 2, 3, and 4, then
  1. needs forks 4 and 1 to eat
  2. needs forks 1 and 2 to eat
  3. needs forks 2 and 3 to eat
  4. needs forks 3 and 4 to eat

At the start, all forks are on the table, available to a philosopher. Thus, all four semaphores must be initialized to one.

To pick up the first fork, a philosopher must get the semaphore for that first, using sem_wait(). This will block until the philosopher can grab it.

If you use the same to pick the other fork, and you're unlucky, you get a deadlock: all forks are already in the hands of the philosophers, and they're all waiting for someone to relinguish a fork so they can start eating, looking like dorks and doing nothing, starving to death.

The trick is to use a nonblocking wait, sem_trywait(), on the second fork. If it succeeds, the philosopher takes a bite to eat, then puts both forks back on the table so that other philosophers get to eat too, using sem_post() on both fork semaphores. If the sem_trywait() fails (returns -1) with errno==EAGAIN, the second fork is already in somebody elses hand, and the philosopher cannot eat. To let somebody else eat and avoid the deadlock, the philosopher must put the first fork back on the table using sem_post(), then retry from the start.

But wait! There is a risk of getting the philosophers locked in a dance: each philosopher grabbing a fork at just the same time, seeing that the other one is already taken, and all putting their forks back on the table at the same time, repeating. There is also a technical issue: if the same process immediately retakes the same semaphore, no other process will ever have time to grab that semaphore; it's just as if the process always held it.

There are two basic solutions to this:

One is to add a short, random wait. (It is added both after putting back the first fork on the table after seeing the other fork is already taken, and after the philosopher has eaten a bit). The first disrupt the non-eating dance, and the second lets the next philosopher have a chance at grabbing the fork before this philosopher takes it again. This is often used when you have a .. randomly-organized banquet hall?, without the organization in this example.

The organization in this example allows for the second option, much superior in my opinion: Switch the order of the forks. After a philosopher has grabbed the left fork first, that philosopher will next grab the right fork first. Also, even philosophers start first with the left fork, and odd philosophers with the right fork. This will ensure that all odd philosophers eat at the same time, then yield for the even philosophers, who get to eat, who in turn yield back to the odd philosophers, and so on, like an organized dance.

When there are an even number of philosophers in a ring, this guarantees that every philosopher gets to take a bite in their turn: when one philosopher is eating, the next philosopher is waiting for the fork to be put on the table. When a philosopher puts their fork back on the table, they turn their attention to the other fork, giving the waiting philosopher to grab the fork. This is why all odd philosophers eat at the same time, alternating with the even philosophers. The fork-grabbing order provides synchronization.

If there were an odd number of philosophers, or if you didn't know the order of the philosophers (that is, you don't know which philosophers sat next to each other), the randomly timed wait would still be necessary. Switching the starting fork from side to side would be useful, since it should avoid the fork dance. The randomly timed wait would still be needed, because if there were many philosophers sitting next to each other trying to eat in the same fork-grabbing order, it might take half as many take-fork-drop-fork cycles as there are synchronized philosophers for the situation to resolve (starting from the edges); the random wait would break that temporary dance much faster.

Is this description what you were asking for?

I don't feel it would be fair to show you the complete code, since aside from the setup (getting shared memory, initializing the semaphores, forking the parallel processes) there really is just a few lines of code needed to implement the philosophers. Personally, I'd put a printf statement, identifying which philosopher got to eat at any time (remember to fflush() to make sure it is output right away!), and also when the philosopher fails to eat. I'd also run it for a limited number of mouthfuls, so the program would end at some point, and I could examine the output to see if there are indications of the fork dance I described earlier, or if everything works smoothly. (Occasional failures to eat are expected, since not all processes really run in parallel all the time; do not try to get "perfect" results. A robust, simple algorithm is better than tweaking it to get perfect results on one machine.)

Obviously, if you have any detailed questions, or need clarifications to the above, we're here to help, but please show your own efforts and understanding first, so we don't feel like we're doing somebody's homework for them.

For myself, I can assure you I really do enjoy helping others to learn for themselves. However, if I find my efforts used for cheating or avoiding having to learn, I will immediately just ignore that member from then on. (LinuxQuestions has an option for that; I won't have to see their posts ever again.)
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
sudo make dinner xcad3ncex LinuxQuestions.org Member Intro 1 07-19-2010 09:51 PM
[SOLVED] C - Semaphores, initiate semaphores seems to be failing golmschenk Programming 3 06-28-2010 09:32 PM
BALUG Dinner Tonight: Open Source Backup & Recovery andrewfife Linux - News 0 10-16-2007 05:44 AM
LXer: FOSS and the philosophers LXer Syndicated Linux News 0 08-09-2007 09:16 PM
Got any implementations of Dining Philosophers with semaphores? meinlinux Programming 3 09-25-2004 05:22 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:08 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration