1
0
Files
irix-657m-src/eoe/cmd/rtmon/rtmond/protocol1.c
2022-09-29 17:59:04 +03:00

339 lines
10 KiB
C

/**************************************************************************
* *
* Copyright (C) 1997, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/*
* WindView protocol support. Event data is reformatted
* according to the old WindView requirements.
*/
#include "rtmond.h"
#include "timer.h"
#include <time.h>
#include <sys/uio.h>
#include <sys/syssgi.h>
#include <sys/param.h>
typedef uint16_t old_event_t;
static void _proto1_flush(daemon_info_t*, client_t*, uint64_t, uint64_t);
static protosw_t protocol1;
static ioblock_t*
iosetup(daemon_info_t* dp, client_t* cp, size_t space)
{
ioblock_t* io;
if ((io = cp->io) == NULL) {
/*
* No current io buffer, get one from the free list.
*/
sem_wait(&cp->iofreelock);
if (cp->io = cp->iofree)
cp->iofree = cp->io->next;
else
cp->io = io_new_buf(dp, cp);
sem_post(&cp->iofreelock);
if (cp->io == NULL)
goto drop;
} else if (io->off + space > io->size) {
/*
* Not enough space in current buffer, push it and
* get another buffer from the free list.
*/
_proto1_flush(dp, cp, 0,0);
if (cp->io == NULL)
goto drop;
}
return (cp->io);
drop:
cp->kdrops++;
IFTRACE(EVENTIO)(dp, "Drop event; %ld bytes; client %s:%u",
space, cp->host, cp->port);
return (NULL);
}
#define IOSETUP(_dp, _cp, _io, _cc) { \
size_t cc = _cc; \
if ((_io = _cp->io) == NULL || _io->off + cc > _io->size) { \
if ((_io = iosetup(_dp, _cp, cc)) == NULL) \
return; \
} \
_cp->kevents++; \
}
/*
* Write the initialization information to the stream.
* To satisfy windview we must write at least
* EVENT_CONFIG and EVENT_BUFFER (see <sys/wrEventP.h>).
*/
static void
_proto1_write_header_info(daemon_info_t* dp, client_t* cp, uint64_t eventmask)
{
char comm_name[256]; /* for undefined task name */
uint32_t name_size;
ioblock_t* io;
(void) eventmask;
IOSETUP(dp, cp, io, 0);
WRITE_BUF(io, old_event_t, EVENT_CONFIG);
WRITE_BUF(io, int32_t, WV_REV_ID|WV_EVT_PROTO_REV);
/* ticks/sec */
WRITE_BUF(io, int32_t, (int32_t) (NSEC_PER_SEC/(cc.cycleval/1000)));
WRITE_BUF(io, int32_t, UINT_MAX); /* timer value at rollover */
WRITE_BUF(io, int32_t, TRUE); /* auto rollover */
WRITE_BUF(io, int32_t, 0); /* clock rate (not used) */
WRITE_BUF(io, int32_t, 0); /* !context switch mode */
WRITE_BUF(io, int32_t, dp->cpu); /* processor number */
WRITE_BUF(io, old_event_t, EVENT_BUFFER);
WRITE_BUF(io, int32_t, (int32_t) dp->last_pid_cache);
#define MANUFACTURER "Silicon Graphics"
name_size = sizeof MANUFACTURER - 1;
WRITE_BUF(io, old_event_t, EVENT_BEGIN);
WRITE_BUF(io, int32_t, (int32_t) dp->cpu_type);
WRITE_BUF(io, int32_t, name_size);
WRITE_BUF_VARIABLE(io, name_size, MANUFACTURER);
WRITE_BUF(io, int32_t, (int32_t) dp->last_pid_cache);
WRITE_BUF(io, int32_t, 0); /* collection mode */
WRITE_BUF(io, int32_t, WV_REV_ID|WV_EVT_PROTO_REV);
strcpy(comm_name, "undefined"); /* NB: can't use literal */
name_size = (strlen(comm_name)+1) &~ 1; /* must be even */
WRITE_BUF(io, old_event_t, EVENT_TASKNAME);
WRITE_BUF(io, uint32_t, 0); /* status */
WRITE_BUF(io, uint32_t, 0); /* pri */
WRITE_BUF(io, uint32_t, 0); /* tasklockcount */
WRITE_BUF(io, int32_t, (int32_t) 0); /* taskid */
WRITE_BUF(io, uint32_t, name_size);
WRITE_BUF_VARIABLE(io, name_size, comm_name);
(void) write(cp->com->fd, io->u.buf, io->off);
io->off = 0;
}
static void
sync_event(daemon_info_t* dp, client_t* cp, __int64_t tstamp)
{
ioblock_t* io;
IOSETUP(dp, cp, io, sizeof (old_event_t) + 2*sizeof (uint32_t));
WRITE_BUF(io, old_event_t, EVENT_TIMER_SYNC);
WRITE_BUF(io, uint32_t, tstamp);
WRITE_BUF(io, uint32_t, tstamp >> 32);
}
#define RTMON_UNPACKPRI(v, p, bp) { p = v&0xffff; bp = (v>>16)&0xffff; }
#define MAX_EVSIZE \
(sizeof (old_event_t) + 3*sizeof (uint32_t) + \
TSTAMP_NUM_QUALS*sizeof (uint64_t))
static void
_proto1_kernel_event(daemon_info_t* dp, client_t* cp, const tstamp_event_entry_t* ke)
{
event_t evt = ke->evt;
ioblock_t* io;
int k;
if (ke->tstamp - cp->lastevt > UINT_MAX) {
if (cp->lastevt)
IFTRACE(SYNC)(dp, "Send sync due to time wrap (kernel event)");
sync_event(dp, cp, ke->tstamp);
}
IOSETUP(dp, cp, io, MAX_EVSIZE);
if (IS_USER_EVENT(evt)) {
/*
* The kernel queue events mapped to user events. Currently the list
* includes:
*
* TSTAMP_EV_EODISP, TSTAMP_EV_YIELD2, TSTAMP_EV_XRUN,
* TSTAMP_EV_INTRQUAL, UNDEFINED_TSTAMP_SYS
*/
WRITE_BUF(io, old_event_t, evt);
WRITE_BUF(io, uint32_t, ke->tstamp);
WRITE_BUF(io, uint32_t, NULL);
WRITE_BUF(io, uint32_t, TSTAMP_NUM_QUALS * sizeof(uint64_t));
for (k = 0; k < TSTAMP_NUM_QUALS; k++)
WRITE_BUF(io, uint64_t, ke->qual[k]);
} else if (IS_INT_ENT_EVENT(evt)) {
WRITE_BUF(io, int16_t, evt);
WRITE_BUF(io, uint32_t, ke->tstamp);
} else {
switch (evt) {
case TSTAMP_EV_INTREXIT:
#if TSTAMP_EV_EVINTREXIT != TSTAMP_EV_INTREXIT
case TSTAMP_EV_EVINTREXIT: /* XXX obsolete tag */
#endif
case EVENT_WIND_EXIT_IDLE:
WRITE_BUF(io, int16_t, evt);
WRITE_BUF(io, uint32_t, ke->tstamp);
break;
case TSTAMP_EV_EOSWITCH: { /* check for rt threads */
int pri, basepri;
RTMON_UNPACKPRI(ke->qual[1], pri, basepri);
WRITE_BUF(io, int16_t,
basepri >= 0 ? TSTAMP_EV_EOSWITCH_RTPRI : TSTAMP_EV_EOSWITCH);
WRITE_BUF(io, uint32_t, ke->tstamp);
WRITE_BUF(io, uint32_t, ke->qual[0]); /* pid */
WRITE_BUF(io, uint32_t, basepri);
break;
}
case EVENT_TASK_STATECHANGE:
WRITE_BUF(io, int16_t, evt);
WRITE_BUF(io, uint32_t, ke->tstamp);
WRITE_BUF(io, uint32_t, ke->qual[0]); /* pid */
WRITE_BUF(io, uint32_t, WIND_PEND); /* XXX */
break;
case TSTAMP_EV_SIGRECV:
case TSTAMP_EV_SIGSEND:
WRITE_BUF(io, int16_t, evt);
WRITE_BUF(io, uint32_t, ke->tstamp);
WRITE_BUF(io, uint32_t, ke->qual[0]); /* pid */
WRITE_BUF(io, uint32_t, ke->qual[2]); /* signum */
break;
case TSTAMP_EV_EXIT:
WRITE_BUF(io, int16_t, evt);
WRITE_BUF(io, uint32_t, ke->qual[0]);
break;
default:
WRITE_BUF(io, int16_t, UNDEFINED_TSTAMP_DAEMON);
WRITE_BUF(io, uint32_t, ke->tstamp);
WRITE_BUF(io, int32_t, NULL);
/*
* The +1 below is for the extra event at the end which is
* the real event number
*/
WRITE_BUF(io, int32_t, (TSTAMP_NUM_QUALS + 1) * sizeof(uint64_t));
for (k = 0; k < TSTAMP_NUM_QUALS; k++)
WRITE_BUF(io, uint64_t, ke->qual[k]);
WRITE_BUF(io, uint64_t, evt);
break;
}
}
}
#undef MAX_EVSIZE
static void
_proto1_user_event(daemon_info_t* dp, client_t* cp, const tstamp_event_entry_t* ue)
{
int k, nquals = ue->qual[0];
ioblock_t* io;
if (ue->tstamp - cp->lastevt > UINT_MAX) {
if (cp->lastevt)
IFTRACE(SYNC)(dp, "Send sync due to time wrap (user event)");
sync_event(dp, cp, ue->tstamp);
}
/*
* A user event is of the form:
* short USER_EVENT;
* int timestamp;
* int spare;
* int nBytes;
* char buffer[nBytes];
*/
IOSETUP(dp, cp, io, sizeof (int16_t) + (3+nquals) * sizeof (int32_t));
WRITE_BUF(io, int16_t, ue->evt);
WRITE_BUF(io, int32_t, ue->tstamp);
WRITE_BUF(io, int32_t, NULL);
WRITE_BUF(io, int32_t, (nquals-1) * sizeof(int32_t));
for (k = 1; k < nquals; k++)
WRITE_BUF(io, int32_t, ue->qual[k]);
}
static void
_proto1_lost_event(daemon_info_t* dp, client_t* cp, __int64_t log_time, int lost_events)
{
ioblock_t* io;
IOSETUP(dp, cp, io, sizeof (old_event_t) + 5*sizeof (int));
WRITE_BUF(io, old_event_t, TSTAMP_EV_LOST_TSTAMP);
WRITE_BUF(io, int, (int) log_time);
WRITE_BUF(io, int, NULL); /* spare */
WRITE_BUF(io, int, 2*sizeof (int)); /* buffer size */
WRITE_BUF(io, int, 2); /* # of quals */
WRITE_BUF(io, int, lost_events);
}
static void
_proto1_write_task_name(daemon_info_t* dp, client_t* cp, pid_t pid, uint64_t tv)
{
#define TASKNAMESIZE \
(sizeof (old_event_t) + 4*sizeof (uint32_t) + sizeof (int32_t) + name_size)
char comm_name[256];
size_t ns = sizeof (comm_name);
uint32_t name_size;
ioblock_t* io;
(void) tv;
pid_lookup_pid(dp, pid, comm_name, &ns);
sprintf(comm_name+ns, "(%ld)", (long) pid); /* tack on pid */
name_size = (strlen(comm_name)+1) &~ 1; /* must be even */
IOSETUP(dp, cp, io, TASKNAMESIZE);
WRITE_BUF(io, old_event_t, EVENT_TASKNAME);
WRITE_BUF(io, uint32_t, 0); /* status */
WRITE_BUF(io, uint32_t, 0); /* pri */
WRITE_BUF(io, uint32_t, 0); /* tasklockcount */
WRITE_BUF(io, int32_t, (int32_t) pid); /* taskid */
WRITE_BUF(io, uint32_t, name_size);
WRITE_BUF_VARIABLE(io, name_size, comm_name);
#undef TASKNAMESIZE
}
void
_proto1_init_client(daemon_info_t* dp, client_t* cp)
{
(void) dp;
cp->lowmark = 0;
}
void
_proto1_init_ioblock(daemon_info_t* dp, ioblock_t* io)
{
(void) dp; (void) io;
}
static void
_proto1_flush(daemon_info_t* dp, client_t* cp, uint64_t tfirst, uint64_t tlast)
{
ssize_t cc;
ioblock_t* io = cp->io;
(void) tfirst; (void) tlast;
if (io != NULL && io->off != 0) {
IFTRACE(EVENTIO)(dp, "Push %ld bytes to Client %s:%u",
(long) io->off, cp->host, cp->port);
io_post(dp, cp);
}
}
static protosw_t protocol1 = {
RTMON_PROTOCOL1,
"WindView Protocol",
_proto1_init_client,
_proto1_init_ioblock,
_proto1_write_header_info,
_proto1_flush,
_proto1_kernel_event,
_proto1_user_event,
_proto1_lost_event,
_proto1_write_task_name
};
void
protocol1_init(void)
{
registerProtocol(&protocol1);
}