#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/queue.h>
#include <netinet/in.h>
#include <setjmp.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <termios.h>
#include <stdbool.h>
#include <ctx.h>
#include <cthread.h>
#include <cthread_barrier.h>
#include <cthread_once.h>
#include "main.h"
#include "phil.h"
const char *doing_str[] = {
" thinking..........",
" wants to eat......",
" wait for forks....",
" eating............",
" ask right fork....",
" wait right fork...",
" ask left fork.....",
" wait left fork....",
" give all forks....",
" ------------------",
NULL
};
static struct cthread_barrier **barriers;
static volatile int phil_quit = 0;
void
phil_create_barriers(void)
{
barriers = calloc(max_threads, sizeof(struct cthread_barrier *));
if (!barriers)
CNE_RET(
"Unable to allocate cthread_barrier structures\n");
}
static BOOL
forks_get(phil_info_t *phil, int my_num,
int solution,
fork_attr_t *forks_attr)
{
BOOL forks_acquired = false;
BOOL pass_turn = false;
int right_fork = my_num;
int left_fork = (my_num + 1) % forks_attr->num_forks;
phil->saved_count = 3;
if (solution == TICKET_BASED) {
if (((forks_attr->forks[right_fork].philosopher == my_num) ||
(forks_attr->forks[right_fork].philosopher == NOBODY)) &&
((forks_attr->forks[left_fork].philosopher == my_num) ||
(forks_attr->forks[left_fork].philosopher == NOBODY)))
forks_acquired = true;
} else {
if (forks_attr->forks[right_fork].status == FORK_IN_USE) {
forks_attr->forks[right_fork].philosopher = my_num;
pass_turn = true;
phil->saved_doing = PHIL_ASK_RIGHT_FORK;
} else if ((forks_attr->forks[right_fork].philosopher != my_num) &&
(forks_attr->forks[right_fork].philosopher != NOBODY)) {
pass_turn = true;
phil->saved_doing = PHIL_WAIT_RIGHT_FORK;
}
if (forks_attr->forks[left_fork].status == FORK_IN_USE) {
forks_attr->forks[left_fork].philosopher = my_num;
pass_turn = true;
phil->saved_doing = PHIL_ASK_LEFT_FORK;
} else if ((forks_attr->forks[left_fork].philosopher != my_num) &
(forks_attr->forks[left_fork].philosopher != NOBODY)) {
pass_turn = true;
phil->saved_doing = PHIL_WAIT_LEFT_FORK;
}
if (!pass_turn) {
forks_attr->forks[right_fork].status = FORK_IN_USE;
forks_attr->forks[left_fork].status = FORK_IN_USE;
forks_attr->forks[right_fork].philosopher = NOBODY;
forks_attr->forks[left_fork].philosopher = NOBODY;
forks_acquired = true;
}
}
phil->saved_count = PHIL_ASK_RIGHT_FORK;
return forks_acquired;
}
static void
forks_put(phil_info_t *phil, int my_num,
int solution,
fork_attr_t *forks_attr)
{
int right_fork = my_num;
int left_fork = (my_num + 1) % forks_attr->num_forks;
phil->saved_count = PHIL_WAIT_RIGHT_FORK;
if (solution == TICKET_BASED) {
forks_attr->forks[right_fork].philosopher =
(right_fork ? right_fork - 1 : (forks_attr->num_forks - 1));
forks_attr->forks[left_fork].philosopher = left_fork;
phil->saved_doing = PHIL_GIVE_FORK;
} else {
forks_attr->forks[right_fork].status = FORK_AVAILABLE;
forks_attr->forks[left_fork].status = FORK_AVAILABLE;
}
phil->saved_count = PHIL_ASK_LEFT_FORK;
}
static void
philosopher_run(void *arg)
{
phil_info_t *phil = arg;
int my_num = phil->idx;
int solution = phil->solution;
phil_attr_t *phils_attr = phil->philos_attr;
fork_attr_t *forks_attr = phil->forks_attr;
stats_t *pStats = phil->stats;
struct cthread_barrier **b = &barriers[
cne_id()];
phils_attr->i_am_ready[my_num] = true;
cne_printf(
"Failed to set private data for thread\n");
return;
}
do {
phil->doing = PHIL_THINKING;
phil->saved_count = 0;
phil->doing = PHIL_WANTS_TO_EAT;
while (forks_get(phil, my_num, solution, forks_attr) == false) {
if (solution == TICKET_BASED)
phil->doing = PHIL_WAIT_FORK;
if (phil->quit)
break;
pStats->go_hungry[my_num]++;
phil->saved_count = 1;
}
phil->doing = PHIL_ASK_RIGHT_FORK;
pStats->food_in_take[my_num]++;
phil->saved_count = 2;
forks_put(phil, my_num, solution, forks_attr);
} while (phil->quit == 0);
}
void
phil_demo_start(void *arg)
{
struct app_info *a = arg;
phil_info_t *phil;
unsigned int solution;
phil_attr_t philos_attr;
fork_attr_t forks_attr;
stats_t stats;
char name[32];
solution = TICKET_BASED;
: a->num_threads;
forks_attr.num_forks = philos_attr.num_phil;
philos_attr.i_am_ready = calloc((size_t)philos_attr.num_phil, sizeof(BOOL));
stats.food_in_take = calloc((size_t)philos_attr.num_phil, sizeof(unsigned int));
forks_attr.forks = calloc((size_t)philos_attr.num_phil, sizeof(fork_t));
stats.go_hungry = calloc((size_t)philos_attr.num_phil, sizeof(unsigned int));
if (forks_attr.forks) {
for (int i = 0; i < philos_attr.num_phil; i++)
forks_attr.forks[i].philosopher = -1;
} else
goto err;
struct cthread_barrier **b = &barriers[id];
snprintf(name, sizeof(name), "Barrier-%d", id);
for (int i = 0; i < philos_attr.num_phil; i++) {
phil = calloc(1, sizeof(phil_info_t));
if (!phil)
CNE_ERR_GOTO(error,
"Unable to allocate philosopher structure %d\n", i);
phil->doing = PHIL_THINKING;
phil->idx = i;
phil->solution = solution;
phil->philos_attr = &philos_attr;
phil->forks_attr = &forks_attr;
phil->stats = &stats;
snprintf(name, sizeof(name), "Philosopher-%d", i);
if (!phil->cthd)
CNE_RET(
"Unable to start philosopher cthread %d\n", i);
}
do {
} while (phil_quit == 0);
error:
err:
free(philos_attr.i_am_ready);
free(stats.food_in_take);
free(stats.go_hungry);
free(forks_attr.forks);
}
void
phil_demo_quit(void)
{
phil_quit = 1;
}
CNDP_API int cne_id(void)
CNDP_API int cne_max_threads(void)
#define CNE_ERR_GOTO(lbl,...)
CNDP_API int cne_printf(const char *fmt,...)
CNDP_API int cthread_barrier_wait(struct cthread_barrier *b)
CNDP_API int cthread_barrier_destroy(struct cthread_barrier *b)
CNDP_API int cthread_mutex_destroy(struct cthread_mutex *mutex)
CNDP_API int cthread_mutex_lock(struct cthread_mutex *mutex)
CNDP_API int cthread_barrier_init(const char *name, struct cthread_barrier **barr, unsigned count)
CNDP_API int cthread_mutex_unlock(struct cthread_mutex *mutex)
CNDP_API struct cthread * cthread_create(const char *name, cthread_func_t func, void *arg)
CNDP_API int cthread_set_thread_private(struct cthread *c, void *arg)
CNDP_API int cthread_mutex_init(const char *name, struct cthread_mutex **mutex, const struct cthread_mutexattr *attr)
CNDP_API void cthread_sleep_msec(uint64_t ms)