Loading...
Searching...
No Matches
examples/libs/shmc/prodcons.c

Simple shared memory example.

Simple shared memory example.

/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* This example uses shared memory between two threads, one producer, one
* consumer.
*/
#include <l4/shmc/shmc.h>
#include <l4/util/util.h>
#include <stdio.h>
#include <string.h>
#include <pthread-l4.h>
#include <l4/sys/thread.h>
#include <l4/sys/debugger.h>
#include <l4/sys/kip.h>
#include <l4/re/env.h>
#define LOG(args...) printf(NAME ": " args)
#define CHK(func) \
do \
{ \
long r = (func); \
if (r) \
{ \
printf(NAME ": Failure %ld (%s) at line %d.\n", \
r, l4sys_errtostr(r), __LINE__); \
return (void *)-1; \
} \
} while (0)
static const char some_data[] = "Hi consumer!";
static inline l4_cap_idx_t self(void) { return pthread_l4_cap(pthread_self()); }
#define NAME "PRODUCER"
static void *thread_producer(void *d)
{
(void)d;
l4shmc_chunk_t p_one;
l4shmc_signal_t s_one, s_done;
l4shmc_area_t shmarea;
l4_kernel_clock_t try_until;
l4_debugger_set_object_name(self(), "producer");
// attach this thread to the shm object
CHK(l4shmc_attach("testshm", &shmarea));
// add a chunk
CHK(l4shmc_add_chunk(&shmarea, "one", 1024, &p_one));
// add a signal
CHK(l4shmc_add_signal(&shmarea, "testshm_prod", &s_one));
CHK(l4shmc_attach_signal(&shmarea, "testshm_done", self(), &s_done));
// connect chunk and signal
CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));
CHK(l4shmc_mark_client_initialized(&shmarea));
try_until = l4_kip_clock(l4re_kip()) + 10 * 1000000;
for (;;)
{
l4_umword_t clients;
l4shmc_get_initialized_clients(&shmarea, &clients);
if (clients == 3UL)
break;
if (l4_kip_clock(l4re_kip()) >= try_until)
{
LOG("consumer not initialized within time\n");
return (void *)-1;
}
}
LOG("Ready.\n");
while (1)
{
while (l4shmc_chunk_try_to_take(&p_one))
printf("Uh, should not happen!\n"); //l4_thread_yield();
memcpy(l4shmc_chunk_ptr(&p_one), some_data, sizeof(some_data));
CHK(l4shmc_chunk_ready_sig(&p_one, sizeof(some_data)));
LOG("Sent data.\n");
CHK(l4shmc_wait_signal(&s_done));
}
l4_sleep_forever();
return NULL;
}
#undef NAME
#define NAME "CONSUMER"
static void *thread_consumer(void *d)
{
(void)d;
l4shmc_area_t shmarea;
l4shmc_chunk_t p_one;
l4shmc_signal_t s_one, s_done;
l4_kernel_clock_t try_until;
l4_debugger_set_object_name(self(), "consumer");
// attach to shared memory area
CHK(l4shmc_attach("testshm", &shmarea));
// get chunk 'one'
CHK(l4shmc_get_chunk(&shmarea, "one", &p_one));
// add a signal
CHK(l4shmc_add_signal(&shmarea, "testshm_done", &s_done));
// attach signal to this thread
CHK(l4shmc_attach_signal(&shmarea, "testshm_prod", self(), &s_one));
// connect chunk and signal
CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));
CHK(l4shmc_mark_client_initialized(&shmarea));
try_until = l4_kip_clock(l4re_kip()) + 10 * 1000000;
for (;;)
{
l4_umword_t clients;
l4shmc_get_initialized_clients(&shmarea, &clients);
if (clients == 3UL)
break;
if (l4_kip_clock(l4re_kip()) >= try_until)
{
LOG("producer not initialized within time\n");
return (void *)-1;
}
}
LOG("Ready.\n");
while (1)
{
CHK(l4shmc_wait_chunk(&p_one));
LOG("Received from chunk one: '%s'.\n",
(char *)l4shmc_chunk_ptr(&p_one));
memset(l4shmc_chunk_ptr(&p_one), 0, l4shmc_chunk_size(&p_one));
CHK(l4shmc_chunk_consumed(&p_one));
CHK(l4shmc_trigger(&s_done));
}
return NULL;
}
int main(void)
{
pthread_t one, two;
long r;
// create shared memory area
if ((r = l4shmc_create("testshm")) < 0)
{
printf("Error %ld (%s) creating shared memory area\n",
r, l4sys_errtostr(r));
return 1;
}
// create two threads, one for producer, one for consumer
pthread_create(&one, 0, thread_producer, 0);
pthread_create(&two, 0, thread_consumer, 0);
// now sleep, the two threads are doing the work
l4_sleep_forever();
return 0;
}
debugger.h
Debugger related definitions.
env.h
Environment interface.
l4re_kip
l4_kernel_info_t const * l4re_kip(void) L4_NOTHROW
Get Kernel Info Page.
Definition env.h:185
l4shmc_create
L4_BEGIN_DECLS long l4shmc_create(char const *shmc_name)
Create a shared memory area.
l4shmc_connect_chunk_signal
long l4shmc_connect_chunk_signal(l4shmc_chunk_t *chunk, l4shmc_signal_t *signal)
Connect a signal with a chunk.
l4shmc_mark_client_initialized
long l4shmc_mark_client_initialized(l4shmc_area_t *shmarea)
Mark this shared memory client as 'initialized'.
l4shmc_get_initialized_clients
long l4shmc_get_initialized_clients(l4shmc_area_t *shmarea, l4_umword_t *bitmask)
Fetch the _clients_init_done bitmask of the shared memory area.
l4shmc_attach
long l4shmc_attach(char const *shmc_name, l4shmc_area_t *shmarea)
Attach to a shared memory area.
l4shmc_chunk_consumed
long l4shmc_chunk_consumed(l4shmc_chunk_t *chunk)
Mark a chunk as free.
l4shmc_wait_chunk
long l4shmc_wait_chunk(l4shmc_chunk_t *chunk)
Wait on a specific chunk.
l4shmc_chunk_size
long l4shmc_chunk_size(l4shmc_chunk_t const *chunk)
Get current size of a chunk.
l4shmc_chunk_ready_sig
long l4shmc_chunk_ready_sig(l4shmc_chunk_t *chunk, l4_umword_t size)
Mark chunk as filled (ready) and signal consumer.
l4shmc_chunk_try_to_take
long l4shmc_chunk_try_to_take(l4shmc_chunk_t *chunk)
Try to mark chunk busy.
l4shmc_get_chunk
long l4shmc_get_chunk(l4shmc_area_t *shmarea, char const *chunk_name, l4shmc_chunk_t *chunk)
Get chunk out of shared memory area.
l4shmc_add_chunk
long l4shmc_add_chunk(l4shmc_area_t *shmarea, char const *chunk_name, l4_umword_t chunk_capacity, l4shmc_chunk_t *chunk)
Add a chunk in the shared memory area.
l4shmc_chunk_ptr
void * l4shmc_chunk_ptr(l4shmc_chunk_t const *chunk)
Get data pointer to chunk.
l4shmc_wait_signal
long l4shmc_wait_signal(l4shmc_signal_t *signal)
Wait on a specific signal.
l4shmc_trigger
long l4shmc_trigger(l4shmc_signal_t *signal)
Trigger a signal.
l4shmc_attach_signal
long l4shmc_attach_signal(l4shmc_area_t *shmarea, char const *signal_name, l4_cap_idx_t thread, l4shmc_signal_t *signal)
Attach to signal.
l4shmc_add_signal
long l4shmc_add_signal(l4shmc_area_t *shmarea, char const *signal_name, l4shmc_signal_t *signal)
Add a signal for the shared memory area.
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_kernel_clock_t
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition l4int.h:53
l4_cap_idx_t
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:336
l4_debugger_set_object_name
l4_msgtag_t l4_debugger_set_object_name(l4_cap_idx_t cap, const char *name) L4_NOTHROW
Set the name of a kernel object.
Definition debugger.h:368
l4_kip_clock
l4_cpu_time_t l4_kip_clock(l4_kernel_info_t const *kip) L4_NOTHROW
Return clock value from the KIP.
Definition kip.h:242
l4_sleep_forever
void l4_sleep_forever(void) L4_NOTHROW L4_NORETURN
Go sleep and never wake up.
Definition util.h:85
shmc.h
Shared memory library header file.
string.h
String.
kip.h
Kernel Info Page access functions.