Example #1
0
/********************************************************************
* Description:  rtapi_support.c
*               This file, 'rtapi_support.c', implements the messaging
*               functions for both kernel and userland thread
*               systems.  See rtapi.h for more info.
*
*               Other than the rest of RTAPI, these functions are linked
*               into the instance module which is loaded before rtapi.so/ko
*               so they are available and message level set before
*               RTAPI starts up
*
*     Copyright 2006-2013 Various Authors
* 
*     This program is free software; you can redistribute it and/or modify
*     it under the terms of the GNU General Public License as published by
*     the Free Software Foundation; either version 2 of the License, or
*     (at your option) any later version.
* 
*     This program is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU General Public License for more details.
* 
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
********************************************************************/


#include "config.h"
#include "rtapi.h"
#include "rtapi/shmdrv/shmdrv.h"
#include "ring.h"

#define RTPRINTBUFFERLEN 1024

#ifdef MODULE
#include "rtapi_app.h"

#include <stdarg.h>		/* va_* */
#include <linux/kernel.h>	/* kernel's vsnprintf */

#define MSG_ORIGIN MSG_KERNEL

#else  /* user land */

#include <stdio.h>		/* libc's vsnprintf() */
#include <sys/types.h>
#include <unistd.h>

#ifdef RTAPI
#define MSG_ORIGIN MSG_RTUSER
#else
#define MSG_ORIGIN MSG_ULAPI
#endif

#endif

// these message levels are used in RTAPI and ULAPI
// respectively until the global segment is attached;
// thereafter switch to using the message levels from there.
#ifdef RTAPI
static int rt_msg_level = RTAPI_MSG_INFO;    // RTAPI (u+k)
#else
static int ulapi_msg_level = RTAPI_MSG_INFO; // ULAPI
#endif

#ifdef ULAPI
ringbuffer_t rtapi_message_buffer;   // rtapi_message ring access strcuture
# else
extern ringbuffer_t rtapi_message_buffer;
#endif

static char logtag[TAGSIZE];

// switch to exclusively using the ringbuffer from RT
#define USE_MESSAGE_RING 1

typedef struct {
    rtapi_msgheader_t hdr;
    char buf[RTPRINTBUFFERLEN];
} rtapi_msg_t;
void vs_ring_write(msg_level_t level, const char *format, va_list ap)
{
    int n;
    rtapi_msg_t logmsg;

#if defined(RTAPI) && defined(BUILD_SYS_USER_DSO)
    static pid_t rtapi_pid;
    if (rtapi_pid == 0)
	rtapi_pid = getpid();

#endif

    if (global_data) {
	// one-time initialisation
	if (!rtapi_message_buffer.header) {
	    ringbuffer_init(&global_data->rtapi_messages, &rtapi_message_buffer);
	}
	logmsg.hdr.origin = MSG_ORIGIN;
#if defined(RTAPI) && defined(BUILD_SYS_KBUILD)
	logmsg.hdr.pid = 0;
#endif
#if defined(RTAPI) && defined(BUILD_SYS_USER_DSO)
	logmsg.hdr.pid =  rtapi_pid;
#endif
#if defined(ULAPI)
	logmsg.hdr.pid  = getpid();
#endif
	logmsg.hdr.level = level;
	logmsg.hdr.encoding = MSG_ASCII;
	strncpy(logmsg.hdr.tag, logtag, sizeof(logmsg.hdr.tag));

	// do format outside critical section
	n = vsnprintf(logmsg.buf, RTPRINTBUFFERLEN, format, ap);

	if (rtapi_message_buffer.header->use_wmutex &&
	    rtapi_mutex_try(&rtapi_message_buffer.header->wmutex)) {
	    global_data->error_ring_locked++;
	    return;
	}
	// use copying writer to shorten criticial section
	record_write(&rtapi_message_buffer, (void *) &logmsg,
			       sizeof(rtapi_msgheader_t) + n + 1); // trailing zero
	if (rtapi_message_buffer.header->use_wmutex)
	    rtapi_mutex_give(&rtapi_message_buffer.header->wmutex);
    }
}

#ifdef MODULE
void default_rtapi_msg_handler(msg_level_t level, const char *fmt,
			      va_list ap) {
    char buf[RTPRINTBUFFERLEN];
    vsnprintf(buf, RTPRINTBUFFERLEN, fmt, ap);
    vs_ring_write(level, buf, ap);
}

#else /* user land */
void default_rtapi_msg_handler(msg_level_t level, const char *fmt,
			       va_list ap) {
    // during startup the global segment might not be
    // available yet, so use stderr until then
    if (MMAP_OK(global_data)) {
	vs_ring_write(level, fmt, ap);
    } else {
	vfprintf(stderr, fmt, ap);
    }
}
Example #2
0
int ulapi_main(int instance, int flavor, global_data_t *global)
{
    int retval = 0;
    int rtapikey;
    int size = 0;

    rtapi_instance = instance; // from here on global within ulapi.so

    // shm_common_init(); // common shared memory API needs this

    // the HAL library constructor already has the global
    // shm segment attached, so no need to do it again here
    // since we're not using the rtapi_app_init()/rtapi_app_exit()
    // calling conventions might as well pass it it

    // this sets global_data for use within ulapi.so which
    // has a disjoint symbol namespace from hal_lib
    global_data = global;

    rtapi_print_msg(RTAPI_MSG_DBG,"ULAPI:%d %s %s init\n",
		    rtapi_instance,
		    rtapi_get_handle()->thread_flavor_name,
		    GIT_VERSION);


    if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) {

	rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance);

	// attach to existing RTAPI segment
	// not all thread flavors actuall might use it
	if ((retval = shm_common_new(rtapikey, &size,
				     rtapi_instance, (void **) &rtapi_data, 0))) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: cannot attach rtapi"
			    " segment key=0x%x %s\n",
			    rtapi_instance, rtapikey, strerror(-retval));
	}
	if (size != sizeof(rtapi_data_t)) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: unexpected rtapi shm size:"
			    " expected: %zu actual: %d\n",
			    rtapi_instance, sizeof(rtapi_data_t), size);
	    return -EINVAL;
	}

	if (MMAP_OK(global_data) && MMAP_OK(rtapi_data)) {
	    rtapi_print_msg(RTAPI_MSG_DBG,
			    "ULAPI:%d msglevel=%d/%d halsize=%d"
			    " %s startup %s\n",
			    rtapi_instance,
			    global_data->rt_msg_level,
			    global_data->user_msg_level,
			    global_data->hal_size,
			    GIT_VERSION, retval ? "FAILED" : "OK");
	} else {
	    rtapi_print_msg(RTAPI_MSG_DBG,
			    "ULAPI:%d init failed, realtime not running?"
			    " global=%p rtapi=%p\n",
			    rtapi_instance, global_data, rtapi_data);
	}
    }
    return retval;
}