diff options
Diffstat (limited to 'src/tet3/servlib/sloop.c')
-rw-r--r-- | src/tet3/servlib/sloop.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/tet3/servlib/sloop.c b/src/tet3/servlib/sloop.c new file mode 100644 index 00000000..f1bb50fb --- /dev/null +++ b/src/tet3/servlib/sloop.c @@ -0,0 +1,212 @@ +/* + * SCCS: @(#)sloop.c 1.9 (96/12/02) + * + * UniSoft Ltd., London, England + * + * (C) Copyright 1992 X/Open Company Limited + * + * All rights reserved. No part of this source code may be reproduced, + * stored in a retrieval system, or transmitted, in any form or by any + * means, electronic, mechanical, photocopying, recording or otherwise, + * except as stated in the end-user licence agreement, without the prior + * permission of the copyright owners. + * + * X/Open and the 'X' symbol are trademarks of X/Open Company Limited in + * the UK and other countries. + */ + +#ifndef lint +static char sccsid[] = "@(#)sloop.c 1.9 (96/12/02) TET3 release 3.3"; +#endif + +/************************************************************************ + +SCCS: @(#)sloop.c 1.9 96/12/02 TETware release 3.3 +NAME: sloop.c +PRODUCT: TETware +AUTHOR: Andrew Dingwall, UniSoft Ltd. +DATE CREATED: April 1992 + +DESCRIPTION: + generic server loop processing functions + +MODIFICATIONS: + Andrew Dingwall, UniSoft Ltd., January 1994 + added ptab tracing + + Andrew Dingwall, UniSoft Ltd., December 1996 + removed (time_t == unsigned long) assumption for n-bit portability + +************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <sys/types.h> +#include <time.h> +#include "dtmac.h" +#include "dtmsg.h" +#include "ptab.h" +#include "error.h" +#include "server.h" +#include "servlib.h" +#include "tslib.h" + +#ifndef NOTRACE +#include "ltoa.h" +#include "dtetlib.h" +#endif + +#ifdef NEEDsrcFile +static char srcFile[] = __FILE__; /* file name for error reporting */ +#endif + + +/* static function declarations */ +static void si_procrun PROTOLIST((void)); +static int si_timeouts PROTOLIST((void)); + + +/* +** tet_si_serverloop() - perform a single server process loop iteration +** +** poll for incoming requests, then service any resulting events; +** do timeout processing, then service any resulting events +** +** the tet_ts_poll() routine should perform a poll of all connections to +** processes in states PS_IDLE, PS_RCVMSG, PS_SNDMSG and PS_CONNECT +** if data can be read (PS_IDLE or PS_RCVMSG) or written (PS_SNDMSG +** or PS_CONNECT) without blocking, raise PF_ATTENTION +** change the state to PS_RCVMSG or PS_SNDMSG as appropriate +** if the poll is implemented by doing a non-blocking read or write, +** set the state and flags as described for tet_ts_rcvmsg() +** or tet_ts_sndmsg() +** +** if a new connection request is received, a new ptab element should be +** allocated by tet_ptalloc() and linked to the ptab list by tet_ptadd() - +** if a connection is accepted without reading any data, set the state to +** PS_RCVMSG and raise PF_ATTENTION, otherwise set the state and flags as +** described for tet_ts_rcvmsg() below +** +** tet_ts_poll() should return 1 as soon as i/o is possible, or 0 after +** delay seconds if no i/o is possible +** if delay is -ve, tet_ts_poll() should not return until i/o is possible +*/ + +#define INFINITY ~((time_t) 1 << ((sizeof (time_t) * CHAR_BIT) - 1)) + +void tet_si_serverloop() +{ + register struct ptab *pp; + register time_t timeout; + register int delay, rc; + extern struct ptab *tet_ptab; + + /* see how long it is to the next timeout */ + timeout = INFINITY; + for (pp = tet_ptab; pp; pp = pp->pt_next) { + ASSERT(pp->pt_magic == PT_MAGIC); + if (pp->pt_timeout && pp->pt_timeout < timeout) + timeout = pp->pt_timeout; + } + if (timeout == INFINITY) + delay = tet_ptab ? LONGDELAY : SHORTDELAY; + else if ((delay = (int) (timeout - time((time_t *) 0))) < 0 || + delay > LONGDELAY) + delay = LONGDELAY; + + TRACE3(tet_Tloop, 2, + "tet_si_serverloop TOP: tet_ptab = %s, poll timeout = %s", + tet_i2x(tet_ptab), tet_i2a(delay)); + +#ifndef NOTRACE + if (tet_Tloop) { + TRACE2(tet_Tloop, 10, "process table:%s", + tet_ptab ? "" : " empty"); + for (pp = tet_ptab; pp; pp = pp->pt_next) + TRACE6(tet_Tloop, 10, + "pp = %s, next = %s, proc = %s, state = %s, flags = %s", + tet_i2x(pp), tet_i2x(pp->pt_next), + tet_r2a(&pp->pt_rid), + tet_ptstate(pp->pt_state), + tet_ptflags(pp->pt_flags)); + } +#endif + + /* perform the main loop */ + if ((rc = tet_ts_poll(tet_ptab, delay)) > 0) + si_procrun(); + else if (rc < 0) + exit(1); + if (si_timeouts() > 0) + si_procrun(); +} + +/* +** si_procrun() - scan the process table for processes that need servicing +** call the service routine for those that do +*/ + +static void si_procrun() +{ + extern struct ptab *tet_ptab; + register struct ptab *pp; + register int done; + + TRACE2(tet_Tloop, 8, "si_procrun START: tet_ptab = %s", + tet_i2x(tet_ptab)); + + do { + TRACE2(tet_Tloop, 8, "si_procrun RESTART: tet_ptab = %s", + tet_i2x(tet_ptab)); + done = 1; + for (pp = tet_ptab; pp; pp = pp->pt_next) { + TRACE3(tet_Tloop, 8, "pp = %s, next = %s", + tet_i2x(pp), tet_i2x(pp->pt_next)); + ASSERT(pp->pt_magic == PT_MAGIC); + if (pp->pt_flags & PF_ATTENTION) { + pp->pt_flags &= ~PF_ATTENTION; + tet_si_service(pp); + done = 0; + break; + } + } + } while (!done); + + TRACE2(tet_Tloop, 8, "si_procrun END: tet_ptab = %s", + tet_i2x(tet_ptab)); + + /* call the server-specific end-procrun routine */ + tet_ss_procrun(); +} + +/* +** si_timeouts() - process event timeouts +** +** return 1 if any events need to be serviced, 0 otherwise +*/ + +static int si_timeouts() +{ + extern struct ptab *tet_ptab; + register struct ptab *pp; + register time_t now = time((time_t *) 0); + register int found = 0; + + for (pp = tet_ptab; pp; pp = pp->pt_next) { + ASSERT(pp->pt_magic == PT_MAGIC); + if (pp->pt_timeout > 0 && pp->pt_timeout <= now) { + pp->pt_flags |= PF_TIMEDOUT; + pp->pt_timeout = 0; + TRACE4(tet_Tloop, 4, "%s: about to call tet_ss_timeout: state = %s, flags = %s", + tet_r2a(&pp->pt_rid), + tet_ptstate(pp->pt_state), + tet_ptflags(pp->pt_flags)); + tet_ss_timeout(pp); + found = 1; + } + } + + return(found); +} + |