l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
requires: stdlibs
# boost, cppunit, stdthread
optional: libstdc++
# boost
optional: libsupc++ libboost atkins
# cairo, l4re, libpng, Mesa, readline, slab
optional: l4re_c-util
# cppunit
optional: libcppunit
# httpfs
optional: libl4revfs-fs-httpfs ankh liblwip_netif_ankh
# inputtst
optional: input
# l4util, slab
optional: l4util
# l4util
optional: libsigma0
# libc_thread_safe, pthread, shmc, stdthread, suspend
optional: libpthread
# libgomp, libjpeg
optional: libc_support_misc
# libio, libirq
optional: libio libirq
# libjpeg
optional: libjpeg mag-gfx scout-gfx
# libpng
optional: libl4png_wrap
# Mesa
optional: Mesa libc_be_math libdl
# ncurses
optional: libncurses libc_be_sig libmount libl4revfs-fs-tarfs
# pthread, slab
optional: log
# readline
optional: dope readline libc_be_fs_noop
# own lib (dependency = name)
optional: cairo libbacktrace libgomp rtc shmc slab sqlite libtlsf
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-zA-Z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../
L4DIR ?= $(PKGDIR)/../../..
TARGET = inputtst
SRC_C = main.c
DEPENDS_PKGS = input
REQUIRES_LIBS = input
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,381 @@
/*****************************************************************************/
/**
* \file input/examples/inputtst/main.c
* \brief Test modes of L4INPUT
*
* \date 11/20/2003
* \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
* \author Frank Mehnert <fm3@os.inf.tu-dresden.de>
*
*/
/*
* (c) 2003-2009 Author(s)
* 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.
*/
/* L4 */
#include <l4/util/util.h>
/* C */
#include <stdio.h>
#include <string.h>
/* input */
#include <l4/input/libinput.h>
l4_ssize_t l4libc_heapsize = 128 * 1024;
/*****************************************************************************/
char *events[EV_MAX + 1] = {
[EV_SYN] = "Sync", [EV_KEY] = "Key",
[EV_REL] = "Relative", [EV_ABS] = "Absolute",
[EV_MSC] = "Misc", [EV_SW] = "Switch",
[EV_LED] = "LED", [EV_SND] = "Sound",
[EV_REP] = "Repeat", [EV_FF] = "ForceFeedback",
[EV_PWR] = "Power", [EV_FF_STATUS] = "ForceFeedbackStatus",
};
char *keys[KEY_MAX + 1] = {
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
[KEY_3] = "3", [KEY_4] = "4",
[KEY_5] = "5", [KEY_6] = "6",
[KEY_7] = "7", [KEY_8] = "8",
[KEY_9] = "9", [KEY_0] = "0",
[KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
[KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
[KEY_Q] = "Q", [KEY_W] = "W",
[KEY_E] = "E", [KEY_R] = "R",
[KEY_T] = "T", [KEY_Y] = "Y",
[KEY_U] = "U", [KEY_I] = "I",
[KEY_O] = "O", [KEY_P] = "P",
[KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
[KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
[KEY_A] = "A", [KEY_S] = "S",
[KEY_D] = "D", [KEY_F] = "F",
[KEY_G] = "G", [KEY_H] = "H",
[KEY_J] = "J", [KEY_K] = "K",
[KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
[KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
[KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
[KEY_Z] = "Z", [KEY_X] = "X",
[KEY_C] = "C", [KEY_V] = "V",
[KEY_B] = "B", [KEY_N] = "N",
[KEY_M] = "M", [KEY_COMMA] = "Comma",
[KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
[KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
[KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
[KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
[KEY_F2] = "F2", [KEY_F3] = "F3",
[KEY_F4] = "F4", [KEY_F5] = "F5",
[KEY_F6] = "F6", [KEY_F7] = "F7",
[KEY_F8] = "F8", [KEY_F9] = "F9",
[KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
[KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
[KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
[KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
[KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
[KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
[KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
[KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
[KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
[KEY_F11] = "F11", [KEY_F12] = "F12",
[KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana",
[KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan",
[KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
[KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
[KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
[KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
[KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
[KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
[KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
[KEY_END] = "End", [KEY_DOWN] = "Down",
[KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
[KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
[KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown",
[KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power",
[KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus",
[KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma",
[KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja",
[KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta",
[KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose",
[KEY_STOP] = "Stop", [KEY_AGAIN] = "Again",
[KEY_PROPS] = "Props", [KEY_UNDO] = "Undo",
[KEY_FRONT] = "Front", [KEY_COPY] = "Copy",
[KEY_OPEN] = "Open", [KEY_PASTE] = "Paste",
[KEY_FIND] = "Find", [KEY_CUT] = "Cut",
[KEY_HELP] = "Help", [KEY_MENU] = "Menu",
[KEY_CALC] = "Calc", [KEY_SETUP] = "Setup",
[KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp",
[KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile",
[KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer",
[KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2",
[KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS",
[KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
[KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail",
[KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer",
[KEY_BACK] = "Back", [KEY_FORWARD] = "Forward",
[KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD",
[KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong",
[KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong",
[KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record",
[KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone",
[KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config",
[KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh",
[KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
[KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
[KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
[KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "KEY_NEW",
[KEY_REDO] = "KEY_REDO", [KEY_F13] = "F13",
[KEY_F14] = "F14", [KEY_F15] = "F15",
[KEY_F16] = "F16", [KEY_F17] = "F17",
[KEY_F18] = "F18", [KEY_F19] = "F19",
[KEY_F20] = "F20", [KEY_F21] = "F21",
[KEY_F22] = "F22", [KEY_F23] = "F23",
[KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD",
[KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
[KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
[KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
[KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost",
[KEY_PRINT] = "Print", [KEY_HP] = "HP",
[KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
[KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
[KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
[KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
[KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
[KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel",
[KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up",
[KEY_MEDIA] = "Media", [KEY_SWITCHVIDEOMODE] = "Switch video",
[KEY_KBDILLUMTOGGLE] = "KBDILLUMTOGGLE", [KEY_KBDILLUMDOWN] = "KBDILLUMDOWN",
[KEY_KBDILLUMUP] = "KBDILLUMUP", [KEY_SEND] = "Send",
[KEY_REPLY] = "Reply", [KEY_FORWARDMAIL] = "Forward",
[KEY_SAVE] = "Save", [KEY_DOCUMENTS] = "Documents",
[KEY_UNKNOWN] = "Unknown",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
[BTN_4] = "Btn4", [BTN_5] = "Btn5",
[BTN_6] = "Btn6", [BTN_7] = "Btn7",
[BTN_8] = "Btn8", [BTN_9] = "Btn9",
[BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
[BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
[BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
[BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
[BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
[BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
[BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
[BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
[BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
[BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
[BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
[BTN_B] = "BtnB", [BTN_C] = "BtnC",
[BTN_X] = "BtnX", [BTN_Y] = "BtnY",
[BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
[BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
[BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
[BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
[BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
[BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber",
[BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil",
[BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
[BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
[BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
[KEY_OPTION] = "Option", [KEY_INFO] = "Info",
[KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor",
[KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program",
[KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites",
[KEY_EPG] = "EPG", [KEY_PVR] = "PVR",
[KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language",
[KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle",
[KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom",
[KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard",
[KEY_SCREEN] = "Screen", [KEY_PC] = "PC",
[KEY_TV] = "TV", [KEY_TV2] = "TV2",
[KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2",
[KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2",
[KEY_CD] = "CD", [KEY_TAPE] = "Tape",
[KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner",
[KEY_PLAYER] = "Player", [KEY_TEXT] = "Text",
[KEY_DVD] = "DVD", [KEY_AUX] = "Aux",
[KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio",
[KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory",
[KEY_LIST] = "List", [KEY_MEMO] = "Memo",
[KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red",
[KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow",
[KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp",
[KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First",
[KEY_LAST] = "Last", [KEY_AB] = "AB",
[KEY_NEXT] = "Next", [KEY_RESTART] = "Restart",
[KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle",
[KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous",
[KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN",
[KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "Delete EOL",
[KEY_DEL_EOS] = "Delete EOS", [KEY_INS_LINE] = "Insert line",
[KEY_DEL_LINE] = "Delete line",
[KEY_FN] = "KEY_FN", [KEY_FN_ESC] = "KEY_FN_ESC",
[KEY_FN_F1] = "KEY_FN_F1", [KEY_FN_F2] = "KEY_FN_F2",
[KEY_FN_F3] = "KEY_FN_F3", [KEY_FN_F4] = "KEY_FN_F4",
[KEY_FN_F5] = "KEY_FN_F5", [KEY_FN_F6] = "KEY_FN_F6",
[KEY_FN_F7] = "KEY_FN_F7", [KEY_FN_F8] = "KEY_FN_F8",
[KEY_FN_F9] = "KEY_FN_F9", [KEY_FN_F10] = "KEY_FN_F10",
[KEY_FN_F11] = "KEY_FN_F11", [KEY_FN_F12] = "KEY_FN_F12",
[KEY_FN_1] = "KEY_FN_1", [KEY_FN_2] = "KEY_FN_2",
[KEY_FN_D] = "KEY_FN_D", [KEY_FN_E] = "KEY_FN_E",
[KEY_FN_F] = "KEY_FN_F", [KEY_FN_S] = "KEY_FN_S",
[KEY_FN_B] = "KEY_FN_B",
};
//char *absval[5] = { "Value", "Min ", "Max ", "Fuzz ", "Flat " };
char *relatives[REL_MAX + 1] = {
[REL_X] = "X", [REL_Y] = "Y",
[REL_Z] = "Z", [REL_RX] = "RX",
[REL_RY] = "RY", [REL_RZ] = "RZ",
[REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial",
[REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
};
char *absolutes[ABS_MAX + 1] = {
[ABS_X] = "X", [ABS_Y] = "Y",
[ABS_Z] = "Z", [ABS_RX] = "Rx",
[ABS_RY] = "Ry", [ABS_RZ] = "Rz",
[ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder",
[ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas",
[ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X",
[ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X",
[ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X",
[ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
[ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
[ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
};
char *misc[MSC_MAX + 1] = {
[MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
[MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData",
[MSC_SCAN] = "ScanCode",
};
char *leds[LED_MAX + 1] = {
[LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
[LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
[LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
[LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute",
[LED_MISC] = "Misc", [LED_MAIL] = "Mail",
[LED_CHARGING] = "Charging",
};
char *repeats[REP_MAX + 1] = {
[REP_DELAY] = "Delay", [REP_PERIOD] = "Period",
};
char *sounds[SND_MAX + 1] = {
[SND_CLICK] = "Click", [SND_BELL] = "Bell",
[SND_TONE] = "Tone",
};
char **names[EV_MAX + 1] = {
[EV_SYN] = events, [EV_KEY] = keys,
[EV_REL] = relatives, [EV_ABS] = absolutes,
[EV_MSC] = misc, [EV_LED] = leds,
[EV_SND] = sounds, [EV_REP] = repeats,
};
#define BITS_PER_LONG (sizeof(long) * 8)
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define OFF(x) ((x)%BITS_PER_LONG)
#define BIT(x) (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG)
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
/*****************************************************************************/
/** LOG L4INPUT EVENT TO SCREEN **/
static void log_event(struct l4input *ev)
{
if (!ev->type)
printf("inputtst: XXX type = 0 XXX\n");
printf("Event: type %d (%s), code %d (%s), value %d\n",
ev->type, events[ev->type] ? events[ev->type] : "?",
ev->code,
names[ev->type] ?
(names[ev->type][ev->code] ?
names[ev->type][ev->code] : "?") :
"?", ev->value);
if ((ev->type == EV_KEY) && (ev->value == 1)) {
l4input_pcspkr(800);
l4_sleep(20);
l4input_pcspkr(0);
}
}
/** CALLBACK MODE TEST **/
static L4_CV void event_cb(struct l4input *ev)
{
/* XXX seems stupid but it's historical */
log_event(ev);
}
/** BUFFER MODE TEST **/
static L4_CV void event_buf(void)
{
int rd, i;
static struct l4input ev[64];
while (1) {
l4_sleep(2);
if (!l4input_ispending())
continue;
rd = l4input_flush(ev, 64);
for (i = 0; i < rd; i++)
log_event(&ev[i]);
}
}
/*****************************************************************************/
static int usage(void)
{
printf("Usage: inputtst MODE\n");
printf("MODE is one of:\n");
printf(" -cb callback mode\n");
printf(" -buf buffer mode\n");
return 1;
}
int main(int argc, char **argv)
{
if (argc < 2)
return usage();
if (strcmp(argv[1], "-cb") == 0) {
printf("Testing L4INPUT callback mode...\n");
printf("init => %d\n",
l4input_init(17, event_cb));
l4_sleep_forever();
}
else if (strcmp(argv[1], "-buf") == 0) {
printf("Testing L4INPUT buffer mode...\n");
printf("init => %d\n",
l4input_init(17, NULL));
event_buf();
}
else
return usage();
return 0;
}

View File

@@ -0,0 +1,6 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,6 @@
PKGDIR = ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_cc
SRC_CC = ma+rm.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,112 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C++.
*/
/*
* (c) 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.
*/
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/util/cap_alloc>
#include <l4/sys/err.h>
#include <cstdio>
#include <cstring>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4Re::Mem_alloc::Continuous: Physically continuous memory
* L4Re::Mem_alloc::Pinned: Pinned memory
* L4Re::Mem_alloc::Super_pages: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_periodic_task
SRC_CC = main.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/**
* (c) 2014 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
*
* This file is licensed under the terms of the GNU General Public License 2.
* See the file COPYING-GPL-2 for details.
*/
#include <l4/re/error_helper>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_timeout_queue>
#include <cstdio>
class My_loop_hooks :
public L4::Ipc_svr::Timeout_queue_hooks<My_loop_hooks>,
public L4::Ipc_svr::Ignore_errors
{
public:
/**
* This function is required by Timeout_queue_hooks to get current time.
*/
l4_kernel_clock_t now()
{
return l4_kip_clock(l4re_kip());
}
};
L4Re::Util::Registry_server<My_loop_hooks> server;
/**
* This class implements the code that needs to be run periodically.
*/
class Periodic_task : public L4::Ipc_svr::Timeout_queue::Timeout
{
public:
Periodic_task(int iterations, L4::Ipc_svr::Server_iface *sif)
: _iterations(iterations), _sif(sif)
{
// Add this to the IPC server's Timeout_queue with an absolute timeout.
// The timeout will expire in 5 seconds from now.
_sif->add_timeout(this, l4_kip_clock(l4re_kip()) + 5000000);
}
/**
* This function is called by the Timeout_queue when its timeout expired.
*/
void expired()
{
printf("Timeout expired.\n");
if (!--_iterations)
printf("Bye bye from ex_periodic_task!\n");
else
// We add ourselves back into the Timeout_queue with a new absolute timeout
// that is 5 seconds after the previous timeout.
_sif->add_timeout(this, timeout() + 5000000);
}
private:
int _iterations;
L4::Ipc_svr::Server_iface *_sif;
};
static Periodic_task task(5, &server);
int main()
{
printf("Hello from ex_periodic_task\n");
server.loop();
}

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_physmem_cc
SRC_CC = physmem.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,132 @@
/**
* \file
* \brief Example of getting memory and it physical address
*/
/*
* (c) 2020 Adam Lackorzynski <adam@l4re.org>
*
* This file is part of L4Re and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/dma_space>
#include <l4/re/protocols.h>
#include <l4/re/error_helper>
#include <l4/re/util/unique_cap>
#include <l4/sys/err.h>
#include <l4/sys/factory>
#include <cstdio>
#include <cstring>
#include <cassert>
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
unsigned long phys_align, void **virt_addr,
L4Re::Util::Unique_cap<L4Re::Dma_space> &dmaspace,
L4Re::Dma_space::Dma_addr *phys_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
flags |= L4Re::Mem_alloc::Continuous;
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d,
flags, phys_align)))
return r;
/* Make the dataspace visible in our address space, uncached */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr
| L4Re::Rm::F::RW
| L4Re::Rm::F::Cache_uncached,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* The the physical memory address of the allocated memory */
if ((r = dmaspace->associate(L4::Ipc::Cap<L4::Task>(),
L4Re::Dma_space::Phys_space)))
return r;
l4_size_t ps = size_in_bytes;
if ((r = dmaspace->map(L4::Ipc::make_cap_rw(d), 0, &ps,
L4Re::Dma_space::Attributes::None,
L4Re::Dma_space::Bidirectional, phys_addr)))
return r;
// The memory is L4Re::Mem_alloc::Continuous, i.e., there is only
// one size.
assert(ps == size_in_bytes);
/* Done, virtual address is in virt_addr */
return 0;
}
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
L4Re::Env const *e = L4Re::Env::env();
void *virt;
auto dmaspace = L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dma_space>());
L4Re::Dma_space::Dma_addr phys;
int r;
if ((r = l4_error(e->user_factory()->create(dmaspace.get()))))
return r;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, // size
0, // flags
2 + L4_PAGESHIFT, // 16 KByte aligned
&virt, dmaspace, &phys))
{
printf("The memory allocation failed\n");
return 1;
}
printf("Allocated memory, virtual address: %p\n", virt);
printf("Physical / DMA address: %llx\n", phys);
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
/* Free memory */
if (free_mem(virt))
return 2;
dmaspace->disassociate();
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ds_clnt ex_l4re_ds_srv
SRC_CC_ex_l4re_ds_clnt = ds_clnt.cc
SRC_CC_ex_l4re_ds_srv = ds_srv.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,110 @@
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@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.
*/
#include <l4/re/util/cap_alloc> // L4::Cap
#include <l4/re/dataspace> // L4Re::Dataspace
#include <l4/re/rm> // L4::Rm
#include <l4/re/env> // L4::Env
#include <l4/sys/cache.h>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include "interface.h"
int main()
{
/*
* Try to get server interface cap.
*/
L4::Cap<My_interface> svr = L4Re::Env::env()->get_cap<My_interface>("shm");
if (!svr.is_valid())
{
printf("Could not get the server capability\n");
return 1;
}
/*
* Alloc data space cap slot
*/
L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!ds.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Alloc server notifier IRQ cap slot
*/
L4::Cap<L4::Irq> irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
if (!irq.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Request shared data-space cap.
*/
if (svr->get_shared_buffer(ds, irq))
{
printf("Could not get shared memory dataspace!\n");
return 1;
}
/*
* Attach to arbitrary region
*/
char *addr = 0;
int err = L4Re::Env::env()->rm()->attach(&addr, ds->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
return 1;
}
printf("Content: %s\n", addr);
// wait a bit for the demo effect
printf("Sleeping a bit...\n");
sleep(1);
/*
* Fill in new stuff
*/
memset(addr, 0, ds->size());
char const * const msg = "Hello from client, too!";
printf("Setting new content in shared memory\n");
snprintf(addr, strlen(msg)+1, msg);
l4_cache_clean_data((unsigned long)addr,
(unsigned long)addr + strlen(msg) + 1);
// notify the server
irq->trigger();
/*
* Detach region containing addr, result should be Detached_ds (other results
* only apply if we split regions etc.).
*/
err = L4Re::Env::env()->rm()->detach(addr, 0);
if (err)
printf("Failed to detach region\n");
/* Free objects and capabilties, just for completeness. */
L4Re::Util::cap_alloc.free(ds, L4Re::This_task);
L4Re::Util::cap_alloc.free(irq, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,220 @@
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@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.
*/
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/re/namespace>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_server>
#include <l4/util/util.h>
#include <l4/sys/typeinfo_svr>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <thread>
#include "interface.h"
/**
* A very simple server object, just providing the
* shared memory data space and an IRQ object to send a notification.
*/
class My_server_obj : public L4::Server_object_t<L4::Kobject>
{
private:
/**
* The capability to the shared memory.
*/
L4::Cap<L4Re::Dataspace> _shm;
L4::Cap<L4::Irq> _irq;
public:
/**
* Create a new object for the given data space.
*/
explicit My_server_obj(L4::Cap<L4Re::Dataspace> shm, L4::Cap<L4::Irq> irq)
: _shm(shm), _irq(irq)
{}
/**
* Dispatch function, dealing with remote requests.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int My_server_obj::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// we don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void) obj;
l4_msgtag_t t;
ios >> t; // extract the tag
switch (t.label())
{
case L4::Meta::Protocol:
// handle the meta protocol requests, implementing the
// runtime dynamic type system for L4 objects.
return L4::Util::handle_meta_request<My_interface>(ios);
case 0:
// since we have just one operation we have no opcode dispatch,
// and just return the data-space and the notifier IRQ capabilities
ios << _shm << _irq;
return 0;
default:
// every other protocol is not supported.
return -L4_EBADPROTO;
}
}
/**
* A simple Server object attached to a notifier IRQ.
* This provides a kind of interrupt handler integrated in our
* server.
*/
class Shm_observer : public L4::Irq_handler_object
{
private:
/**
* The pointer to the shared memory.
*/
char *_shm;
public:
/**
* Create a new object for the given shared memory.
*/
explicit Shm_observer(char *shm)
: _shm(shm)
{}
/**
* Dispatch function, dealing with remote requests.
* This is the ISR.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int Shm_observer::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// We don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void)obj;
// Since we end up here in this function, we got a 'message' from the IRQ
// that is bound to us. The 'ios' stream won't contain any valuable info.
(void)ios;
printf("Client sent us: %s\n", _shm);
return 0;
}
enum
{
DS_SIZE = 4 << 12,
};
static char *get_ds(L4::Cap<L4Re::Dataspace> *_ds)
{
*_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!(*_ds).is_valid())
{
printf("Dataspace allocation failed.\n");
return 0;
}
int err = L4Re::Env::env()->mem_alloc()->alloc(DS_SIZE, *_ds, 0);
if (err < 0)
{
printf("mem_alloc->alloc() failed.\n");
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Attach DS to local address space
*/
char *_addr = 0;
err = L4Re::Env::env()->rm()->attach(&_addr, (*_ds)->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(*_ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Success! Write something to DS.
*/
printf("Attached DS\n");
static char const * const msg = "[DS] Hello from server!";
snprintf(_addr, strlen(msg) + 1, msg);
return _addr;
}
static void *server_thread(void *)
{
L4::Cap<L4::Thread> l4_thread = Pthread::L4::cap(pthread_self());
L4Re::Util::Registry_server<> server(l4_thread, L4Re::Env::env()->factory());
L4::Cap<L4Re::Dataspace> ds;
char *addr;
if (!(addr = get_ds(&ds)))
return nullptr;
// First the IRQ handler, because we need it in the My_server_obj object
Shm_observer observer(addr);
// Registering the observer as an IRQ handler, this allocates an
// IRQ object using the factory of our server.
L4::Cap<L4::Irq> irq = server.registry()->register_irq_obj(&observer);
// Now the initial server object shared with the client via our parent.
// it provides the data-space and the IRQ capabilities to a client.
My_server_obj server_obj(ds, irq);
// Registering the server object to the capability 'shm' in our the L4Re::Env.
// This capability must be provided by the parent. (see the shared_ds.lua)
server.registry()->register_obj(&server_obj, "shm");
// Run our server loop.
server.loop();
}
int main()
{
pthread_attr_t pattr;
if (pthread_attr_init(&pattr))
L4Re::throw_error(-L4_ENOMEM, "Initialize pthread attributes");
pthread_t thr;
L4Re::chksys(pthread_create(&thr, &pattr, server_thread, nullptr),
"Create server thread");
L4Re::chksys(pthread_attr_destroy(&pattr), "Destroy pthread attributes");
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include <l4/sys/capability>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_stream>
/**
* Interface class for remote object.
*
* Inherits from L4::Kobject, via the L4::Kobject_t helper
* template that generates the dynamic type information for the meta
* protocol.
*/
class My_interface : public L4::Kobject_t<My_interface, L4::Kobject>
{
// Disable instantiation and copy, because we just work via
// L4::Cap<...> references.
L4_KOBJECT(My_interface)
public:
/**
* The single method of our object.
* Requesting the data space and the IRQ to notify the server.
*/
int get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw();
};
inline
int
My_interface::get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw()
{
L4::Ipc::Iostream s(l4_utcb());
// we have just a single operation, so no opcode needed
// s << Opcode;
// put receive buffer for data-space cap and the irq cap into the stream
s << L4::Ipc::Small_buf(ds)
<< L4::Ipc::Small_buf(irq);
return l4_error(s.call(cap()));
}

View File

@@ -0,0 +1,27 @@
-- Include L4 functionality
local L4 = require("L4");
-- Create a channel from the client to the server
local channel = L4.default_loader:new_channel();
-- Start the server, giving the channel with full server rights.
-- The server will have a yellow log output.
L4.default_loader:start(
{
caps = { shm = channel:svr() },
log = { "server", "yellow" }
},
"rom/ex_l4re_ds_srv"
);
-- Start the client, giving it the channel with read only rights. The
-- log output will be green.
L4.default_loader:start(
{
caps = { shm = channel },
log = { "client", "green" },
l4re_dbg = L4.Dbg.Warn
},
"rom/ex_l4re_ds_clnt"
);

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_c
SRC_C = ma+rm.c
REQUIRES_LIBS = l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,113 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C.
*/
/*
* (c) 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.
*/
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/sys/err.h>
#include <stdio.h>
#include <string.h>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4RE_MA_CONTINUOUS: Physically continuous memory
* L4RE_MA_PINNED: Pinned memory
* L4RE_MA_SUPER_PAGES: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
l4re_ds_t ds;
/* Allocate a free capability index for our data space */
ds = l4re_util_cap_alloc();
if (l4_is_invalid_cap(ds))
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = l4re_ma_alloc(size_in_bytes, ds, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = l4re_rm_attach(virt_addr, size_in_bytes,
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX, ds, 0,
flags & L4RE_MA_SUPER_PAGES
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
{
/* Free dataspace again */
l4re_util_cap_free_um(ds);
return r;
}
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
l4re_ds_t ds;
/* Detach memory from our address space */
if ((r = l4re_rm_detach_ds(virt_addr, &ds)))
return r;
/* Free memory at our memory allocator */
l4re_util_cap_free_um(ds);
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_smap-server ex_smap-client
SRC_CC_ex_smap-server = server.cc
SRC_CC_ex_smap-client = client.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@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.
*/
#include <l4/sys/err.h>
#include <l4/sys/types.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/cxx/ipc_stream>
#include <stdio.h>
#include "shared.h"
static int
func_smap_call(L4::Cap<void> const &server)
{
L4::Ipc::Iostream s(l4_utcb());
l4_addr_t addr = 0;
int err;
if ((err = L4Re::Env::env()->rm()->reserve_area(&addr, L4_PAGESIZE,
L4Re::Rm::F::Search_addr)))
{
printf("The reservation of one page within our virtual memory failed with %d\n", err);
return 1;
}
s << L4::Opcode(Mapper::Do_map)
<< (l4_addr_t)addr;
s << L4::Ipc::Rcv_fpage::mem((l4_addr_t)addr, L4_PAGESHIFT, 0);
int r = l4_error(s.call(server.cap(), Mapper::Protocol));
if (r)
return r; // failure
printf("String sent by server: %s\n", (char *)addr);
return 0; // ok
}
int
main()
{
L4::Cap<void> server = L4Re::Env::env()->get_cap<void>("smap");
if (!server.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
printf("Asking for page from server\n");
if (func_smap_call(server))
{
printf("Error talking to server\n");
return 1;
}
printf("It worked!\n");
L4Re::Util::cap_alloc.free(server, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,76 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@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.
*/
#include <stdio.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_server>
#include "shared.h"
static char page_to_map[L4_PAGESIZE] __attribute__((aligned(L4_PAGESIZE)));
static L4Re::Util::Registry_server<> server;
class Smap_server : public L4::Server_object_t<Mapper>
{
public:
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int
Smap_server::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
{
l4_msgtag_t t;
ios >> t;
// We're only talking the Map_example protocol
if (t.label() != Mapper::Protocol)
return -L4_EBADPROTO;
L4::Opcode opcode;
ios >> opcode;
switch (opcode)
{
case Mapper::Do_map:
l4_addr_t snd_base;
ios >> snd_base;
// put something into the page to read it out at the other side
snprintf(page_to_map, sizeof(page_to_map), "Hello from the server!");
printf("Sending to client\n");
// send page
ios << L4::Ipc::Snd_fpage::mem((l4_addr_t)page_to_map, L4_PAGESHIFT,
L4_FPAGE_RO, snd_base);
return L4_EOK;
default:
return -L4_ENOSYS;
}
}
int
main()
{
static Smap_server smap;
// Register server
if (!server.registry()->register_obj(&smap, "smap").is_valid())
{
printf("Could not register my service, read-only namespace?\n");
return 1;
}
printf("Welcome to the memory map example server!\n");
// Wait for client requests
server.loop();
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* (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.
*/
#pragma once
#include <l4/sys/capability>
struct Mapper : public L4::Kobject_t<Mapper, L4::Kobject>
{
enum Opcodes { Do_map };
};

View File

@@ -0,0 +1,21 @@
-- vim:set ft=lua:
-- Include L4 functionality
local L4 = require("L4");
-- Channel for the communication between the server and the client.
local smap_channel = L4.default_loader:new_channel();
-- The server program, using the 'smap' channel in server
-- mode. The log prefix will be 'server', colored yellow.
L4.default_loader:start({ caps = { smap = smap_channel:svr() },
log = { "server", "yellow" }},
"rom/ex_smap-server");
-- The client program.
-- It is given the 'smap' channel to be able to talk to the server.
-- The log prefix will be 'client', colored green.
L4.default_loader:start({ caps = { smap = smap_channel },
log = { "client", "green" } },
"rom/ex_smap-client");

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = uclibc_thread_safe
SRC_CC = main.cc
REQUIRES_LIBS = libpthread
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,100 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Frank Mehnert <fm3@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.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <l4/util/util.h>
#include <l4/sys/kdebug.h>
#if defined(ARCH_x86) || defined(ARCH_amd64)
#include <l4/util/rdtsc.h>
#endif
#include <l4/re/env.h>
#include <pthread.h>
#include <l4/l4re_vfs/backend>
#if !defined(ARCH_x86) && !defined(ARCH_amd64)
static void l4_busy_wait_ns(unsigned long val)
{
static volatile int fooo = 0;
unsigned long i;
for (i = val/10; i > 0; --i)
++fooo;
}
#endif
static void *
thread(void *id)
{
printf("\033[31merrno_location[%ld] = %08lx\033[m\n",
(unsigned long)id, (l4_addr_t)__errno_location());
for (;;)
{
if (id == (void*)1)
puts("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
else
puts("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
l4_busy_wait_ns(1000000);
}
return NULL;
}
namespace {
using namespace L4Re::Vfs;
class myops : public Be_file
{
public:
ssize_t writev(const struct iovec *i, int) throw();
int fstat64(struct stat64 *buf) const throw()
{ (void)buf; return 0; }
};
ssize_t
myops::writev(const struct iovec *i, int) throw()
{
const char *b = (char *)i->iov_base;
size_t c = i->iov_len;
while (c--)
{
outchar(*b++);
l4_busy_wait_ns(1000000);
}
return i->iov_len;
}
static void f() __attribute__((constructor));
static void f()
{
static myops mo;
mo.add_ref();
L4Re::Vfs::vfs_ops->set_fd(STDOUT_FILENO, cxx::ref_ptr(&mo));
}
}
int
main(void)
{
#if defined(ARCH_x86) || defined(ARCH_amd64)
l4_calibrate_tsc(l4re_kip());
#endif
dup2(STDOUT_FILENO, STDERR_FILENO);
pthread_t t1, t2;
pthread_create(&t1, NULL, thread, (void *)1);
pthread_create(&t2, NULL, thread, (void *)2);
l4_sleep_forever();
}

View File

@@ -0,0 +1,25 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
DEPENDS_PKGS = libgomp
# missing sync_* functions in (my) sparc compiler
SYSTEMS = $(filter-out sparc-l4f,$(SYSTEMS_ABI))
include $(L4DIR)/mk/Makeconf
ifneq ($(SYSTEM),)
# check whether used gcc has the omp.h file available
OMP_H_PATH := $(shell $(CC) -print-file-name=include/omp.h)
ifeq ($(strip $(OMP_H_PATH)),include/omp.h)
$(info  $(CC) does not have omp.h header file available, skipping.)
else
TARGET = $(if $(filter 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5,$(GCCVERSION)),ex_omp)
REQUIRES_LIBS = libgomp libc_support_misc
endif
endif
SRC_C = main.c
CFLAGS = -fopenmp
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,22 @@
#include <omp.h>
#include <stdio.h>
#include <semaphore.h>
int main(void)
{
int id, nthreads;
printf("Program launching\n");
#pragma omp parallel private (id)
{
id = omp_get_thread_num();
printf("Hello World from thread %d\n", id);
#pragma omp barrier
if (id == 0) {
nthreads = omp_get_num_threads();
printf("There are %d threads\n", nthreads);
}
}
printf("DONE\n");
return 1;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_libio
SRC_C = main.c
REQUIRES_LIBS = libio libirq
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,90 @@
/*
* (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.
*/
#include <l4/io/io.h>
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <l4/sys/kdebug.h>
#include <stdio.h>
void __libio_dump(void);
static void dump_vbus(void)
{
l4io_device_handle_t devhandle = l4io_get_root_device();
l4io_device_t dev;
l4io_resource_handle_t reshandle;
while (!l4io_iterate_devices(&devhandle, &dev, &reshandle))
{
l4io_resource_t res;
printf("device: type=%x name=%s numres=%d flags=%x\n",
dev.type, dev.name, dev.num_resources, dev.flags);
while (!l4io_lookup_resource(devhandle, L4IO_RESOURCE_ANY,
&reshandle, &res))
{
printf(" resource: %d %x %lx-%lx\n",
res.type, res.flags, res.start, res.end);
}
}
}
int main(void)
{
l4_addr_t a1, a2;
l4irq_t *irq12;
fprintf(stderr, "libio_test\n");
dump_vbus();
if (l4io_request_ioport(0x80, 1))
return 1;
fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (l4io_request_ioport(0x90, 0xf))
return 1;
fprintf(stderr, "%s %d\n", __func__, __LINE__);
fprintf(stderr, "Ports 0x80 and 0x90-0x9e should be there\n");
if (!(irq12 = l4irq_attach(12)))
return -1;
if (l4io_request_iomem(0xfe000000, 0x100000, 0, &a1))
return 1;
fprintf(stderr, "0xfe000000 mapped to %lx\n", a1);
if (l4io_request_iomem(0xfa000000, 0x10000, 1, &a2))
return 1;
fprintf(stderr, "0xfa000000 mapped to %lx\n", a2);
fprintf(stderr, "Check mappings, IRQs and ports in JDB\n");
//__libio_dump();
enter_kdebug("check in jdb");
if (l4io_release_iomem(a1, 0x100000))
return 1;
if (l4io_release_ioport(0x90, 0xf))
return 1;
if (l4irq_detach(irq12))
return 1;
fprintf(stderr, "Check that region at %lx and I/O port range 0x90-0x9e and IRQ12 disappeared\n", a1);
//__libio_dump();
enter_kdebug("check in jdb");
return 0;
}

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
SRC_C_ex_libirq_async = async_isr.c
SRC_C_ex_libirq_loop = loop.c
TARGET = ex_libirq_async ex_libirq_loop
REQUIRES_LIBS = libirq libio
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,50 @@
/*
* (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 shall show how to use the libirq.
*/
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <stdio.h>
enum { IRQ_NO = 17 };
static void isr_handler(void *data)
{
(void)data;
printf("Got IRQ %d\n", IRQ_NO);
}
int main(void)
{
const int seconds = 5;
l4irq_t *irqdesc;
if (!(irqdesc = l4irq_request(IRQ_NO, isr_handler, 0, 0xff, 0)))
{
printf("Requesting IRQ %d failed\n", IRQ_NO);
return 1;
}
printf("Attached to key IRQ %d\nPress keys now, will terminate in %d seconds\n",
IRQ_NO, seconds);
l4_sleep(seconds * 1000);
if (l4irq_release(irqdesc))
{
printf("Failed to release IRQ\n");
return 1;
}
printf("Bye\n");
return 0;
}

View File

@@ -0,0 +1,50 @@
/*
* (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.
*/
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <stdio.h>
#include <pthread.h>
enum { IRQ_NO = 17 };
static void isr_handler(void)
{
printf("Got IRQ %d\n", IRQ_NO);
}
static void *isr_thread(void *data)
{
l4irq_t *irq;
(void)data;
if (!(irq = l4irq_attach(IRQ_NO)))
return NULL;
while (1)
{
if (l4irq_wait(irq))
continue;
isr_handler();
}
return NULL;
}
int main(void)
{
pthread_t thread;
if (pthread_create(&thread, NULL, isr_thread, NULL))
return 1;
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_libpng
SRC_C = main.c
REQUIRES_LIBS = libl4png_wrap l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,80 @@
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/c/util/video/goos_fb.h>
#include <l4/libpng/l4png_wrap.h>
#include <l4/util/util.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
void *bildmem;
void *vidmem;
l4re_util_video_goos_fb_t gfb;
l4re_video_view_info_t fbi;
if (argc < 2)
{
printf("Need to give PNG picture to display\n");
return 1;
}
if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
return 45;
if (!(vidmem = l4re_util_video_goos_fb_attach_buffer(&gfb)))
return 46;
printf("size: %lld\n", l4re_ds_size(l4re_util_video_goos_fb_buffer(&gfb)));
printf("Vidmem attached to %p\n", vidmem);
if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
{
printf("l4re_fb_open failed\n");
return 1;
}
int bild = open(argv[1], O_RDONLY);
if (bild == -1)
{
printf("Could not open '%s'.\n", argv[1]);
perror("open");
return 8;
}
struct stat st;
if (fstat(bild, &st) == -1)
return 9;
bildmem = mmap(0, st.st_size, PROT_READ, MAP_SHARED, bild, 0);
if (bildmem == MAP_FAILED)
return 10;
int png_w, png_h;
libpng_get_size_mem(bildmem, st.st_size, &png_w, &png_h);
printf("PNG: %dx%d\n", png_w, png_h);
if (png_w < 0 || png_h < 0)
{
printf("Error with picture. Is it one?\n");
return 1;
}
libpng_render_mem2(bildmem, (void *)vidmem,
st.st_size,
l4re_ds_size(l4re_util_video_goos_fb_buffer(&gfb)),
((int)fbi.width - png_w) / 2,
((int)fbi.height - png_h) / 2,
&fbi);
l4re_util_video_goos_fb_refresh(&gfb, 0, 0, png_w, png_h);
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
SRC_C = main.c
TARGET = rtc_test
DEPENDS_PKGS = rtc
REQUIRES_LIBS = rtc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,43 @@
/**
* \file
* \brief Small RTC server test
*/
/*
* (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.
*/
#include <l4/rtc/rtc.h>
#include <l4/util/util.h>
#include <l4/re/env.h>
#include <stdio.h>
int main(void)
{
l4_uint64_t value;
l4_cap_idx_t server = l4re_env_get_cap("rtc");
if (!l4_is_valid_cap(server))
{
printf("Error finding 'rtc' cap.\n");
return 1;
}
if (l4rtc_get_offset_to_realtime(server, &value))
printf("Error: l4rtc_get_offset_to_realtime\n");
else
printf("offset-to-realtime: %lld\n", value);
while (1)
{
l4_uint64_t now = l4rtc_get_timer() + value;
printf("time: %lldns\n", now);
l4_sleep(400);
}
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_shmc
SRC_C = prodcons.c
REQUIRES_LIBS = shmc libpthread
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,192 @@
/*
* (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;
}

View File

@@ -0,0 +1,22 @@
-- vi:ft=lua
local L4 = require "L4";
-- The IRQ capabilities need the 'S' right to allow threads to attach to the
-- corresponding objects.
local irq_prod = L4.Env.factory:create(L4.Proto.Irq_sender)
local irq_done = L4.Env.factory:create(L4.Proto.Irq_sender)
local shm = L4.Env.user_factory:create(L4.Proto.Dataspace, 8192)
L4.default_loader:start(
{
caps =
{
jdb = L4.Env.jdb,
testshm_prod = irq_prod:m("rws"),
testshm_done = irq_done:m("rws"),
testshm = shm:m("rw"),
},
log = {"ex_shmc", "c"}
}, "rom/ex_shmc")