/*===========================================================================* * do_sigprocmask * *===========================================================================*/ int do_sigprocmask() { /* Note that the library interface passes the actual mask in sigmask_set, * not a pointer to the mask, in order to save a copy. Similarly, * the old mask is placed in the return message which the library * interface copies (if requested) to the user specified address. * * The library interface must set SIG_INQUIRE if the 'act' argument * is NULL. * * KILL and STOP can't be masked. */ int i; mp->mp_reply.reply_mask = (long) mp->mp_sigmask; switch (m_in.sig_how) { case SIG_BLOCK: sigdelset((sigset_t *)&m_in.sig_set, SIGKILL); sigdelset((sigset_t *)&m_in.sig_set, SIGSTOP); for (i = 1; i < _NSIG; i++) { if (sigismember((sigset_t *)&m_in.sig_set, i)) sigaddset(&mp->mp_sigmask, i); } break; case SIG_UNBLOCK: for (i = 1; i < _NSIG; i++) { if (sigismember((sigset_t *)&m_in.sig_set, i)) sigdelset(&mp->mp_sigmask, i); } check_pending(mp); break; case SIG_SETMASK: sigdelset((sigset_t *) &m_in.sig_set, SIGKILL); sigdelset((sigset_t *) &m_in.sig_set, SIGSTOP); mp->mp_sigmask = (sigset_t) m_in.sig_set; check_pending(mp); break; case SIG_INQUIRE: break; default: return(EINVAL); break; } return OK; }
/*===========================================================================* * do_sigsuspend * *===========================================================================*/ PUBLIC int do_sigsuspend() { mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */ mp->mp_sigmask = (sigset_t) m_in.sig_set; sigdelset(&mp->mp_sigmask, SIGKILL); mp->mp_flags |= SIGSUSPENDED; check_pending(mp); return(SUSPEND); }
/*===========================================================================* * do_sigsuspend * *===========================================================================*/ int do_sigsuspend(void) { assert(!(mp->mp_flags & (PROC_STOPPED | VFS_CALL | UNPAUSED))); mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */ mp->mp_sigmask = m_in.m_lc_pm_sigset.set; sigdelset(&mp->mp_sigmask, SIGKILL); sigdelset(&mp->mp_sigmask, SIGSTOP); mp->mp_flags |= SIGSUSPENDED; check_pending(mp); return(SUSPEND); }
/** * Handles an incoming REGSITER message from a client. */ void handle_register(struct pr_group_list_t *group, int hostidx, const unsigned char *message, unsigned meslen, uint32_t src) { const struct register_h *reg; const unsigned char *enckey; struct pr_destinfo_t *dest; int dupmsg; reg = (const struct register_h *)message; enckey = (const unsigned char *)reg + sizeof(struct register_h); if (group->destcount == MAXPROXYDEST) { glog1(group, "Rejecting REGISTER from %08X: max destinations exceeded", ntohl(src)); send_downstream_abort(group, src, "Max destinations exceeded", 0); return; } if ((meslen < (reg->hlen * 4U)) || ((reg->hlen * 4U) < sizeof(struct register_h) + ntohs(reg->keyinfo_len))) { glog1(group, "Rejecting REGISTER from %08X: invalid message size", ntohl(src)); send_downstream_abort(group, src, "Invalid message size", 0); return; } if (hostidx == -1) { hostidx = add_client(src, group); } dest = &group->destinfo[hostidx]; dupmsg = (dest->registered == 1); dest->registered = 1; dest->regtime.tv_sec = ntohl(reg->tstamp_sec); dest->regtime.tv_usec = ntohl(reg->tstamp_usec); if (dest->state != PR_CLIENT_REGISTERED) { if (group->keytype != KEY_NONE) { if (!handle_register_keys(reg, enckey, group, hostidx, src)) { return; } } if (!group->client_auth || dest->pubkey.key) { dest->state = PR_CLIENT_REGISTERED; } } glog2(group, "Received REGISTER%s from %s", dupmsg ? "+" : "", dest->name); if (dest->state == PR_CLIENT_REGISTERED) { check_pending(group, hostidx, message); } }
/*===========================================================================* * do_sigreturn * *===========================================================================*/ PUBLIC int do_sigreturn() { /* A user signal handler is done. Restore context and check for * pending unblocked signals. */ int r; mp->mp_sigmask = (sigset_t) m_in.sig_set; sigdelset(&mp->mp_sigmask, SIGKILL); r = sys_sigreturn(who, (struct sigmsg *) m_in.sig_context); check_pending(mp); return(r); }
/*===========================================================================* * do_sigreturn * *===========================================================================*/ int do_sigreturn(void) { /* A user signal handler is done. Restore context and check for * pending unblocked signals. */ int r; assert(!(mp->mp_flags & (PROC_STOPPED | VFS_CALL | UNPAUSED))); mp->mp_sigmask = m_in.m_lc_pm_sigset.set; sigdelset(&mp->mp_sigmask, SIGKILL); sigdelset(&mp->mp_sigmask, SIGSTOP); r = sys_sigreturn(who_e, (struct sigmsg *)m_in.m_lc_pm_sigset.ctx); check_pending(mp); return(r); }
/** * Handles an incoming FILEINFO_ACK message from a client */ void handle_fileinfo_ack(struct pr_group_list_t *group, int hostidx, const unsigned char *message, unsigned meslen) { const struct fileinfoack_h *fileinfoack; struct pr_destinfo_t *dest; fileinfoack = (const struct fileinfoack_h *)message; dest = &group->destinfo[hostidx]; if ((meslen < (fileinfoack->hlen * 4U)) || ((fileinfoack->hlen * 4U) < sizeof(struct fileinfoack_h))) { log1(group->group_id, group->group_inst, ntohs(fileinfoack->file_id), "Rejecting FILEINFO_ACK from %s: invalid message size", dest->name); return; } log2(group->group_id, group->group_inst, ntohs(fileinfoack->file_id), "Received FILEINFO_ACK from %s", dest->name); check_pending(group, hostidx, message); }
/*===========================================================================* * do_trace * *===========================================================================*/ PUBLIC int do_trace() { register struct mproc *child; struct ptrace_range pr; int i, r, seg, req; req = m_in.request; /* The T_OK call is made by the child fork of the debugger before it execs * the process to be traced. The T_ATTACH call is made by the debugger itself * to attach to an existing process. */ switch (req) { case T_OK: /* enable tracing by parent for this proc */ if (mp->mp_tracer != NO_TRACER) return(EBUSY); mp->mp_tracer = mp->mp_parent; mp->mp_reply.reply_trace = 0; return(OK); case T_ATTACH: /* attach to an existing process */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); /* For non-root processes, user and group ID must match. */ if (mp->mp_effuid != SUPER_USER && (mp->mp_effuid != child->mp_effuid || mp->mp_effgid != child->mp_effgid || child->mp_effuid != child->mp_realuid || child->mp_effgid != child->mp_realgid)) return(EPERM); /* Only root may trace system servers. */ if (mp->mp_effuid != SUPER_USER && (child->mp_flags & PRIV_PROC)) return(EPERM); /* System servers may not trace anyone. They can use sys_trace(). */ if (mp->mp_flags & PRIV_PROC) return(EPERM); /* Can't trace self, PM or VM. */ if (child == mp || child->mp_endpoint == PM_PROC_NR || child->mp_endpoint == VM_PROC_NR) return(EPERM); /* Can't trace a process that is already being traced. */ if (child->mp_tracer != NO_TRACER) return(EBUSY); child->mp_tracer = who_p; child->mp_trace_flags = TO_NOEXEC; sig_proc(child, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */); mp->mp_reply.reply_trace = 0; return(OK); case T_STOP: /* stop the process */ /* This call is not exposed to user programs, because its effect can be * achieved better by sending the traced process a signal with kill(2). */ return(EINVAL); case T_READB_INS: /* special hack for reading text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); case T_WRITEB_INS: /* special hack for patching text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); #if 0 /* Should check for shared text */ /* Make sure the text segment is not used as a source for shared * text. */ child->mp_ino = 0; child->mp_dev = 0; child->mp_ctime = 0; #endif r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); } /* All the other calls are made by the tracing process to control execution * of the child. For all these calls, the child must be stopped. */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); if (child->mp_tracer != who_p) return(ESRCH); if (!(child->mp_flags & STOPPED)) return(EBUSY); switch (req) { case T_EXIT: /* exit */ child->mp_flags |= TRACE_EXIT; /* Defer the exit if the traced process has an VFS call pending. */ if (child->mp_flags & VFS_CALL) child->mp_exitstatus = (int) m_in.data; /* save for later */ else exit_proc(child, (int) m_in.data, FALSE /*dump_core*/); /* Do not reply to the caller until VFS has processed the exit * request. */ return(SUSPEND); case T_SETOPT: /* set trace options */ child->mp_trace_flags = m_in.data; mp->mp_reply.reply_trace = 0; return(OK); case T_GETRANGE: case T_SETRANGE: /* get/set range of values */ r = sys_datacopy(who_e, (vir_bytes) m_in.PMTRACE_ADDR, SELF, (vir_bytes) &pr, (phys_bytes) sizeof(pr)); if (r != OK) return(r); if (pr.pr_space != TS_INS && pr.pr_space != TS_DATA) return(EINVAL); if (pr.pr_size == 0 || pr.pr_size > LONG_MAX) return(EINVAL); seg = (pr.pr_space == TS_INS) ? T : D; if (req == T_GETRANGE) r = sys_vircopy(child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, who_e, D, (vir_bytes) pr.pr_ptr, (phys_bytes) pr.pr_size); else r = sys_vircopy(who_e, D, (vir_bytes) pr.pr_ptr, child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, (phys_bytes) pr.pr_size); if (r != OK) return(r); mp->mp_reply.reply_trace = 0; return(OK); case T_DETACH: /* detach from traced process */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); child->mp_tracer = NO_TRACER; /* Let all tracer-pending signals through the filter. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { (void) sigdelset(&child->mp_sigtrace, i); check_sig(child->mp_pid, i, FALSE /* ksig */); } } if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, TRUE /*trace*/, FALSE /* ksig */); } /* Resume the child as if nothing ever happened. */ child->mp_flags &= ~STOPPED; child->mp_trace_flags = 0; check_pending(child); break; case T_RESUME: case T_STEP: case T_SYSCALL: /* resume execution */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, FALSE /*trace*/, FALSE /* ksig */); } /* If there are any other signals waiting to be delivered, * feign a successful resumption. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { mp->mp_reply.reply_trace = 0; return(OK); } } child->mp_flags &= ~STOPPED; check_pending(child); break; } r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); }
/* * Put a variable's value to a PV, with timeout. */ epicsShareFunc pvStat seq_pvPutTmo(SS_ID ss, CH_ID chId, enum compType compType, double tmo) { PROG *sp = ss->prog; CHAN *ch = sp->chan + chId; pvStat status; unsigned count; char *var = valPtr(ch,ss); /* ptr to value */ PVREQ *req; DBCHAN *dbch = ch->dbch; PVMETA *meta = metaPtr(ch,ss); DEBUG("pvPut: pv name=%s, var=%p\n", dbch ? dbch->dbName : "<anonymous>", var); /* First handle anonymous PV (safe mode only) */ if (optTest(sp, OPT_SAFE) && !dbch) { anonymous_put(ss, ch); return pvStatOK; } if (!dbch) { errlogSevPrintf(errlogMajor, "pvPut(%s): user error (not assigned to a PV)\n", ch->varName ); return pvStatERROR; } /* Check for channel connected */ status = check_connected(dbch, meta); if (status != pvStatOK) return status; /* Determine whether to perform synchronous, asynchronous, or plain put ((+a) option was never honored for put, so DEFAULT means fire-and-forget) */ status = check_pending(pvEventPut, ss, ss->putReq + chId, ch->varName, dbch, meta, compType, tmo); if (status != pvStatOK) return status; /* Determine number of elements to put (don't try to put more than db count) */ count = dbch->dbCount; /* Perform the PV put operation (either non-blocking or with a callback routine specified) */ if (compType == DEFAULT) { status = pvVarPutNoBlock( &dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var); /* data value */ if (status != pvStatOK) { pv_call_failure(dbch, meta, status); errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutNoBlock() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); return status; } } else { /* Allocate and initialize a pv request */ req = (PVREQ *)freeListMalloc(sp->pvReqPool); req->ss = ss; req->ch = ch; assert(ss->putReq[chId] == NULL); ss->putReq[chId] = req; status = pvVarPutCallback( &dbch->pvid, /* PV id */ ch->type->putType, /* data type */ count, /* element count */ (pvValue *)var, /* data value */ req); /* user arg */ if (status != pvStatOK) { pv_call_failure(dbch, meta, status); errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutCallback() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); ss->putReq[chId] = NULL; /* cancel the request */ freeListFree(sp->pvReqPool, req); check_connected(dbch, meta); return status; } if (compType == SYNC) /* wait for completion */ { pvSysFlush(sp->pvSys); status = wait_complete(pvEventPut, ss, ss->putReq + chId, dbch, meta, tmo); if (status != pvStatOK) return status; } } return pvStatOK; }
/* * Get value from a channel, with timeout. */ epicsShareFunc pvStat seq_pvGetTmo(SS_ID ss, CH_ID chId, enum compType compType, double tmo) { PROG *sp = ss->prog; CHAN *ch = sp->chan + chId; pvStat status; PVREQ *req; DBCHAN *dbch = ch->dbch; PVMETA *meta = metaPtr(ch,ss); /* Anonymous PV and safe mode, just copy from shared buffer. Note that completion is always immediate, so no distinction between SYNC and ASYNC needed. See also pvGetComplete. */ if (optTest(sp, OPT_SAFE) && !dbch) { /* Copy regardless of whether dirty flag is set or not */ ss_read_buffer(ss, ch, FALSE); return pvStatOK; } /* No named PV and traditional mode => user error */ if (!dbch) { errlogSevPrintf(errlogMajor, "pvGet(%s): user error (not assigned to a PV)\n", ch->varName ); return pvStatERROR; } if (compType == DEFAULT) { compType = optTest(sp, OPT_ASYNC) ? ASYNC : SYNC; } status = check_pending(pvEventGet, ss, ss->getReq + chId, ch->varName, dbch, meta, compType, tmo); if (status != pvStatOK) return status; /* Allocate and initialize a pv request */ req = (PVREQ *)freeListMalloc(sp->pvReqPool); req->ss = ss; req->ch = ch; assert(ss->getReq[chId] == NULL); ss->getReq[chId] = req; /* Perform the PV get operation with a callback routine specified. Requesting more than db channel has available is ok. */ status = pvVarGetCallback( &dbch->pvid, /* PV id */ ch->type->getType, /* request type */ ch->count, /* element count */ req); /* user arg */ if (status != pvStatOK) { pv_call_failure(dbch, meta, status); errlogSevPrintf(errlogFatal, "pvGet(var %s, pv %s): pvVarGetCallback() failure: %s\n", ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid)); ss->getReq[chId] = NULL; /* cancel the request */ freeListFree(sp->pvReqPool, req); check_connected(dbch, meta); return status; } /* Synchronous: wait for completion */ if (compType == SYNC) { pvSysFlush(sp->pvSys); status = wait_complete(pvEventGet, ss, ss->getReq + chId, dbch, meta, tmo); if (status != pvStatOK) return status; if (optTest(sp, OPT_SAFE)) /* Copy regardless of whether dirty flag is set or not */ ss_read_buffer(ss, ch, FALSE); } return pvStatOK; }
/*===========================================================================* * process_ksig * *===========================================================================*/ int process_ksig(endpoint_t proc_nr_e, int signo) { register struct mproc *rmp; int proc_nr; pid_t proc_id, id; if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0) { printf("PM: process_ksig: %d?? not ok\n", proc_nr_e); return EDEADEPT; /* process is gone. */ } rmp = &mproc[proc_nr]; if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) { #if 0 printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e); #endif return EDEADEPT; /* process is gone. */ } proc_id = rmp->mp_pid; mp = &mproc[0]; /* pretend signals are from PM */ mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ /* For SIGVTALRM and SIGPROF, see if we need to restart a * virtual timer. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0 * to indicate a broadcast to the recipient's process group. For * SIGKILL, use proc_id -1 to indicate a systemwide broadcast. */ switch (signo) { case SIGINT: case SIGQUIT: case SIGWINCH: id = 0; break; /* broadcast to process group */ case SIGVTALRM: case SIGPROF: check_vtimer(proc_nr, signo); /* fall-through */ default: id = proc_id; break; } check_sig(id, signo, TRUE /* ksig */); /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was * still sending, and the kernel hereby tells us that the process is now done * with that. We can now try to resume what we planned to do in the first * place: set up a signal handler. However, the process's message may have * been a call to PM, in which case the process may have changed any of its * signal settings. The process may also have forked, exited etcetera. */ if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) { rmp->mp_flags &= ~DELAY_CALL; /* * If the VFS_CALL flag is still set we have a process which is stopped * and we only need to wait for a reply from VFS. We are going to check * the pending signal then */ if (rmp->mp_flags & VFS_CALL) return OK; if (rmp->mp_flags & PM_SIG_PENDING) panic("process_ksig: bad process state"); /* Process as many normal signals as possible. */ check_pending(rmp); if (rmp->mp_flags & DELAY_CALL) panic("process_ksig: multiple delay calls?"); } /* See if the process is still alive */ if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE) { return OK; /* signal has been delivered */ } else { return EDEADEPT; /* process is gone */ } }
int main(int argc, char *argv[]) { int i, t = 0; uint32 done = 0; char ch, benchmark = 0, noinput = 0; hd_engine *engine; circle_object obj[6]; for (i = 1; i < argc; i++) { if (*argv[i] == '-') { if (strcmp("benchmark", argv[i]+1) == 0) benchmark = 1; if (strcmp("noinput", argv[i]+1) == 0) noinput = 1; } } noinput = noinput && benchmark; #ifndef IPOD if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr,"Unable to init SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); screen = SDL_SetVideoMode(WIDTH, HEIGHT,16,SDL_SWSURFACE); if (screen == NULL) { fprintf(stderr,"Unable to init SDL video: %s\n",SDL_GetError()); exit(1); } engine = HD_Initialize (WIDTH, HEIGHT, 16, screen->pixels, update); #define IMGPREFIX "" #else HD_LCD_Init(); HD_LCD_GetInfo (0, &WIDTH, &HEIGHT, 0); screen = xmalloc (WIDTH * HEIGHT * 2); engine = HD_Initialize (WIDTH, HEIGHT, 16, screen, update); #define IMGPREFIX "" #endif obj[4].object = HD_PNG_Create (IMGPREFIX "bg.png"); obj[4].object->x = 0; obj[4].object->y = 0; obj[4].object->w = WIDTH; obj[4].object->h = HEIGHT; obj[0].object = HD_PNG_Create (IMGPREFIX "photos.png"); obj[0].object->x = 0; obj[0].object->y = 0; obj[0].object->w = 75 * WIDTH / 220; obj[0].object->h = 150 * WIDTH / 220; obj[1].object = HD_PNG_Create (IMGPREFIX "music.png"); obj[1].object->x = 0; obj[1].object->y = 0; obj[1].object->w = 75 * WIDTH / 220; obj[1].object->h = 150 * WIDTH / 220; obj[2].object = HD_PNG_Create (IMGPREFIX "dvd.png"); obj[2].object->x = 0; obj[2].object->y = 0; obj[2].object->w = 75 * WIDTH / 220; obj[2].object->h = 150 * WIDTH / 220; obj[3].object = HD_PNG_Create (IMGPREFIX "movies.png"); obj[3].object->x = 0; obj[3].object->y = 0; obj[3].object->w = 75 * WIDTH / 220; obj[3].object->h = 150 * WIDTH / 220; obj[5].object = HD_Canvas_Create (100, 100); obj[5].object->x = 100; obj[5].object->y = 100; HD_Register(engine,obj[4].object); HD_Register(engine,obj[0].object); HD_Register(engine,obj[1].object); HD_Register(engine,obj[2].object); HD_Register(engine,obj[3].object); if (obj[5].object) HD_Register(engine,obj[5].object); obj[0].position = 0; obj[1].position = 1024; obj[2].position = 2048; obj[3].position = 3072; object_topwid = ((50 * WIDTH / 220) << 16) / obj[0].object->w; object_bottomwid = ((70 * WIDTH / 220) << 16) / obj[0].object->w; if (benchmark) { HD_AnimateCircle(obj[0].object, 80 * WIDTH / 220, 50 * HEIGHT / 176, 50 * HEIGHT / 176, object_topwid, object_bottomwid, obj[0].position, 4096, -100); HD_AnimateCircle(obj[1].object, 80 * WIDTH / 220, 50 * HEIGHT / 176, 50 * HEIGHT / 176, object_topwid, object_bottomwid, obj[1].position, 4096, -100); HD_AnimateCircle(obj[2].object, 80 * WIDTH / 220, 50 * HEIGHT / 176, 50 * HEIGHT / 176, object_topwid, object_bottomwid, obj[2].position, 4096, -100); HD_AnimateCircle(obj[3].object, 80 * WIDTH / 220, 50 * HEIGHT / 176, 50 * HEIGHT / 176, object_topwid, object_bottomwid, obj[3].position, 4096, -100); } else { circle_rotate(&obj[0], 1); circle_rotate(&obj[1], 1); circle_rotate(&obj[2], 1); circle_rotate(&obj[3], 1); } #ifdef IPOD uint32 srtc = *(volatile uint32 *)0x60005010; set_keypress(); fd_set rd; struct timeval tv; int n; #endif while(!done) { if (!benchmark && (ch = check_pending()) && !obj[0].object->animating) { circle_rotate(&obj[0], ch); circle_rotate(&obj[1], ch); circle_rotate(&obj[2], ch); circle_rotate(&obj[3], ch); } #ifndef IPOD SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_SPACE: case SDLK_BACKSPACE: case SDLK_DOWN: case SDLK_UP: break; case SDLK_RIGHT: if (benchmark) break; if (obj[0].object->animating) { add_pending(1); break; } circle_rotate(&obj[0], 1); circle_rotate(&obj[1], 1); circle_rotate(&obj[2], 1); circle_rotate(&obj[3], 1); break; case SDLK_LEFT: if (benchmark) break; if (obj[0].object->animating) { add_pending(-1); break; } circle_rotate(&obj[0], -1); circle_rotate(&obj[1], -1); circle_rotate(&obj[2], -1); circle_rotate(&obj[3], -1); break; case SDLK_ESCAPE: done = 1; break; default: break; } break; case SDL_QUIT: return(0); break; default: break; } } SDL_Delay (30); #else #define SCROLL_MOD_NUM 24 // 100/25 - 1 #define SCROLL_MOD(n) \ ({ \ static int sofar = 0; \ int use = 0; \ if (++sofar >= n) { \ sofar -= n; \ use = 1; \ } \ (use == 1); \ }) if (!noinput) { FD_ZERO(&rd); FD_SET(0, &rd); tv.tv_sec = 0; tv.tv_usec = 100; n = select(0+1, &rd, NULL, NULL, &tv); if (FD_ISSET(0, &rd) && (n > 0)) { read(0, &ch, 1); switch(ch) { case 'm': done = 1; break; case 'r': if (SCROLL_MOD(SCROLL_MOD_NUM)) { if (benchmark) break; if (obj[0].object->animating) { add_pending(1); break; } circle_rotate(&obj[0], 1); circle_rotate(&obj[1], 1); circle_rotate(&obj[2], 1); circle_rotate(&obj[3], 1); } break; case 'l': if (SCROLL_MOD(SCROLL_MOD_NUM)) { if (benchmark) break; if (obj[0].object->animating) { add_pending(-1); break; } circle_rotate(&obj[0], -1); circle_rotate(&obj[1], -1); circle_rotate(&obj[2], -1); circle_rotate(&obj[3], -1); } break; case 'w': case 'f': case 'd': default: break; } } } #endif t++; if (benchmark && t > 200) done = 1; HD_Animate (engine); #ifndef IPOD if( SDL_MUSTLOCK(screen) ) SDL_LockSurface(screen); #endif HD_Render(engine); #ifndef IPOD if( SDL_MUSTLOCK(screen) ) SDL_UnlockSurface(screen); #endif } #ifdef IPOD HD_LCD_Quit(); uint32 ertc = *(volatile uint32 *)0x60005010; printf ("%d frames in %d microseconds = %d.%02d frames/sec\n", t, ertc - srtc, 1000000 * t / (ertc - srtc), (1000000 * t / ((ertc - srtc) / 100)) % 100); sleep (5); reset_keypress(); #endif HD_Deinitialize(engine); return(0); }
/*===========================================================================* * process_ksig * *===========================================================================*/ int process_ksig(endpoint_t proc_nr_e, int signo) { register struct mproc *rmp; int proc_nr; pid_t proc_id, id; if(pm_isokendpt(proc_nr_e, &proc_nr) != OK) { printf("PM: process_ksig: %d?? not ok\n", proc_nr_e); return EDEADEPT; /* process is gone. */ } rmp = &mproc[proc_nr]; if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) { #if 0 printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e); #endif return EDEADEPT; /* process is gone. */ } proc_id = rmp->mp_pid; mp = &mproc[0]; /* pretend signals are from PM */ mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ /* For SIGVTALRM and SIGPROF, see if we need to restart a * virtual timer. For SIGINT, SIGINFO, SIGWINCH and SIGQUIT, use proc_id 0 * to indicate a broadcast to the recipient's process group. For * SIGKILL, use proc_id -1 to indicate a systemwide broadcast. */ switch (signo) { case SIGINT: case SIGQUIT: case SIGWINCH: case SIGINFO: id = 0; break; /* broadcast to process group */ case SIGVTALRM: case SIGPROF: check_vtimer(proc_nr, signo); /* fall-through */ default: id = proc_id; break; } check_sig(id, signo, TRUE /* ksig */); /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was * still sending, and the kernel hereby tells us that the process is now done * with that. We can now try to resume what we planned to do in the first * place: set up a signal handler. However, the process's message may have * been a call to PM, in which case the process may have changed any of its * signal settings. The process may also have forked, exited etcetera. */ if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) { /* When getting SIGSNDELAY, the process is stopped at least until the * receipt of the SIGSNDELAY signal is acknowledged to the kernel. The * process is not stopped on PROC_STOP in the kernel. However, now that * there is no longer a delay call, stop_proc() is guaranteed to * succeed immediately. */ rmp->mp_flags &= ~DELAY_CALL; assert(!(rmp->mp_flags & PROC_STOPPED)); /* If the delay call was to PM, it may have resulted in a VFS call. In * that case, we must wait with further signal processing until VFS has * replied. Stop the process. */ if (rmp->mp_flags & VFS_CALL) { stop_proc(rmp, FALSE /*may_delay*/); return OK; } /* Process as many normal signals as possible. */ check_pending(rmp); assert(!(rmp->mp_flags & DELAY_CALL)); } /* See if the process is still alive */ if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE) { return OK; /* signal has been delivered */ } else { return EDEADEPT; /* process is gone */ } }
/** * Handles an incoming CLIENT_KEY message from a client. */ void handle_clientkey(struct pr_group_list_t *group, int hostidx, const unsigned char *message, unsigned meslen, uint32_t src) { const struct client_key_h *clientkey; const unsigned char *keyblob, *verify; struct pr_destinfo_t *dest; int dupmsg; clientkey = (const struct client_key_h *)message; keyblob = (const unsigned char *)clientkey + sizeof(struct client_key_h); verify = keyblob + ntohs(clientkey->bloblen); if (group->destcount == MAXPROXYDEST) { glog1(group, "Rejecting CLIENT_KEY from %08X: " "max destinations exceeded", ntohl(src)); send_downstream_abort(group, src, "Max destinations exceeded", 0); return; } if ((meslen < (clientkey->hlen * 4U)) || ((clientkey->hlen * 4U) < sizeof(struct client_key_h) + ntohs(clientkey->bloblen) + ntohs(clientkey->siglen))) { glog1(group, "Rejecting CLIENT_KEY from %08X: invalid message size", ntohl(src)); send_downstream_abort(group, src, "Invalid message size", 0); return; } if ((((group->keyextype == KEYEX_RSA) || (group->keyextype == KEYEX_ECDH_RSA)) && (keyblob[0] != KEYBLOB_RSA)) || ((group->keyextype == KEYEX_ECDH_ECDSA) && (keyblob[0] != KEYBLOB_EC))) { glog1(group, "Rejecting CLIENT_KEY from %08X: invalid keyblob type", ntohl(src)); send_downstream_abort(group, src, "Invalid keyblob type", 0); return; } if (hostidx == -1) { hostidx = add_client(src, group); } dest = &group->destinfo[hostidx]; dupmsg = (dest->pubkey.key != 0); if (!dest->verified) { if (keyblob[0] == KEYBLOB_RSA) { if (!import_RSA_key(&dest->pubkey.rsa, keyblob, ntohs(clientkey->bloblen))) { glog1(group, "Failed to load client public key"); send_downstream_abort(group, src, "Failed to load client public key", 0); return; } dest->pubkeylen = RSA_keylen(dest->pubkey.rsa); } else { if (!import_EC_key(&dest->pubkey.ec, keyblob, ntohs(clientkey->bloblen), 0)) { glog1(group, "Failed to load client public key"); send_downstream_abort(group, src, "Failed to load client public key", 0); return; } dest->pubkeylen = ECDSA_siglen(dest->pubkey.ec); } if (!verify_fingerprint(client_fp, client_fp_count, keyblob, ntohs(clientkey->bloblen), group, src)) { glog1(group, "Failed to verify client key fingerprint"); send_downstream_abort(group, src, "Failed to verify client key fingerprint", 0); return; } dest->verified = 1; } memcpy(dest->verifydata, verify, ntohs(clientkey->siglen)); dest->verifylen = ntohs(clientkey->siglen); if (dest->registered) { if (!verify_client_key(group, hostidx)) { return; } dest->state = PR_CLIENT_REGISTERED; } glog2(group,"Received CLIENT_KEY%s from %s", dupmsg ? "+" : "", dest->name); if (dest->state == PR_CLIENT_REGISTERED) { // Pass in a dummy REGISTER message to check_pending, since // CLIENT_KEY is basically an extension of REGISTER. struct register_h reg; reg.func = REGISTER; check_pending(group, hostidx, (unsigned char *)®); } }