blob: 391f0e2edaaaf1c689de65b53258b5d3c53e256a [file] [log] [blame]
/* phil_fiber.c - dining philosopher */
/*
* Copyright (c) 2011-2016 Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zephyr.h>
#include <tc_util.h>
#include "phil.h"
#ifdef CONFIG_NANOKERNEL
#define FORK(x) (&forks[x])
#define TAKE(x) nano_fiber_sem_take(x, TICKS_UNLIMITED)
#define GIVE(x) nano_fiber_sem_give(x)
#else /* ! CONFIG_NANOKERNEL */
#define FORK(x) forks[x]
#define TAKE(x) task_mutex_lock(x, TICKS_UNLIMITED)
#define GIVE(x) task_mutex_unlock(x)
#endif /* CONFIG_NANOKERNEL */
#define RANDDELAY(x) my_delay(((sys_tick_get_32() * ((x) + 1)) & 0x1f) + 1)
#ifdef CONFIG_NANOKERNEL
/* externs */
extern struct nano_sem forks[N_PHILOSOPHERS];
#else /* ! CONFIG_NANOKERNEL */
kmutex_t forks[] = {fork_mutex0, fork_mutex1, fork_mutex2, fork_mutex3, fork_mutex4};
#endif /* CONFIG_NANOKERNEL */
/**
*
* @brief Wait for a number of ticks to elapse
*
* @param ticks Number of ticks to delay.
*
* @return N/A
*/
static void my_delay(int ticks)
{
#ifdef CONFIG_MICROKERNEL
task_sleep(ticks);
#else
struct nano_timer timer;
nano_timer_init(&timer, (void *) 0);
nano_fiber_timer_start(&timer, ticks);
nano_fiber_timer_test(&timer, TICKS_UNLIMITED);
#endif
}
/**
*
* @brief Entry point to a philosopher's thread
*
* This routine runs as a task in the microkernel environment
* and as a fiber in the nanokernel environment.
*
* @return N/A
*/
void phil_entry(void)
{
int counter;
#ifdef CONFIG_NANOKERNEL
struct nano_sem *f1; /* fork #1 */
struct nano_sem *f2; /* fork #2 */
#else
kmutex_t f1; /* fork #1 */
kmutex_t f2; /* fork #2 */
#endif
static int myId; /* next philosopher ID */
int pri = irq_lock(); /* interrupt lock level */
int id = myId++; /* current philosopher ID */
irq_unlock(pri);
/* always take the lowest fork first */
if ((id+1) != N_PHILOSOPHERS) {
f1 = FORK(id);
f2 = FORK(id + 1);
} else {
f1 = FORK(0);
f2 = FORK(id);
}
for (counter = 0; counter < 5; counter++) {
TAKE(f1);
TAKE(f2);
RANDDELAY(id);
GIVE(f2);
GIVE(f1);
RANDDELAY(id);
}
}