reclaim.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 551 行 · 第 1/2 页

C
551
字号
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <vxWorks.h>#include <version.h>#include <string.h>#include <types.h>#include <sigLib.h>#include <ioLib.h>#include <iosLib.h>#include <fioLib.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <symLib.h>#include <sysLib.h>#include <sysSymTbl.h>#include <loadLib.h>#include <taskLib.h>#include <taskVarLib.h>#include <taskHookLib.h>#include <tickLib.h>#include <time.h>#include <rngLib.h>#include <semLib.h>#include <selectLib.h>#include <sockLib.h>#include <a_out.h>#include <wdLib.h>#include <timers.h>#include <ctype.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <stdarg.h>#include <stdio.h>#include <math.h>#include <limits.h>#include <stdlib.h>#include <string.h>#define RECLAIM_NO_ALIAS /* No #defines for open/malloc/fopen etc */#include "reclaim.h"#include "reclaim_private.h"#undef open#undef creat#undef socket#undef accept#undef close#undef fopen#undef fdopen#undef freopen#undef fclose/* XXX Should do opendir/closedir too... */#undef malloc#undef calloc#undef realloc#undef free#undef cfree#ifdef _ARCH_PPC #define MAX_FILES_SYM_NAME "maxFiles"#else#define MAX_FILES_SYM_NAME "_maxFiles"#endif/*  * Use another free() function upon task deletion?  * Note! When changing free function, the new free function will have to * be able to cope with ALL previously used malloced areas, that is  * it has to be able to find out how things are malloced * to free them in the right way! */static FreeFunction reclaim_free_function = NULL;/* delete hook handling (see below) */static int hook_added = 0;	/* Initated at first reclaim_init, an extra				 non MT-safe check that we only get 				 initialized once *//* Forward... */static void save_reclaim(WIND_TCB *tcbp);struct mall_data {    struct mall_data *next;    char *self;};struct task_data {    FUNCPTR version;		/* To recognize when we have reloaded */    int max_files;		/* It may change... */    struct fd_set open_fds;    struct mall_data *mall_data;    FUNCPTR delete_hook;    caddr_t hook_data;    FILE *open_fps[1];		/* Will be max_files long */} *task_data = NULL;static int max_files = 50;	/* default configAll.h */int reclaim_max_files(void){    return max_files;}#ifdef DEBUG#define check_hook() \((task_data != NULL || \  fdprintf(2,"check_hook() TID = 0x%08x, Called from line %d\n", \	  (unsigned int)taskIdSelf(),\	  __LINE__)) && \(task_data != NULL || \ (taskVarAdd(0, (int *)&task_data) == OK && \ (task_data = (struct task_data *)\ calloc(1, sizeof(struct task_data) + max_files*sizeof(FILE *))) != NULL && \   (task_data->version = (FUNCPTR)save_reclaim) != NULL && \   (task_data->max_files = max_files) != 0 && \  fdprintf(2,"taskVar Added for 0x%08x\n",(unsigned int)taskIdSelf()))))#else#define check_hook() \(task_data != NULL || \ (taskVarAdd(0, (int *)&task_data) == OK && \ (task_data = (struct task_data *)\ calloc(1, sizeof(struct task_data) + max_files*sizeof(FILE *))) != NULL && \   (task_data->version = (FUNCPTR)save_reclaim) != NULL && \   (task_data->max_files = max_files) != 0))#endif/* * Global initialization of the reclaim data structures, mainly * the max_files variable. This HAS to be called by some task before  * the first task that utilizes this exit's, preferrably before any * task makes the first use of this library. */STATUS reclaim_init(void){    int *mp;    SYM_TYPE type;    struct task_data *tdp;    int i;    if (!hook_added) {	/* race condition */	++hook_added;	/* Try to find the maxFiles value */	if (symFindByNameAndType(sysSymTbl, MAX_FILES_SYM_NAME, (char **)&mp, 				 &type,				 N_EXT | N_BSS, N_EXT | N_BSS) == OK ||	    symFindByNameAndType(sysSymTbl, MAX_FILES_SYM_NAME, (char **)&mp, 				 &type,				 N_EXT | N_DATA, N_EXT | N_DATA) == OK) {#ifdef DEBUG	    fdprintf(2, "Found maxFiles=%d\n", *mp);#endif	    if (*mp <= FD_SETSIZE)		max_files = *mp;	    else		max_files = FD_SETSIZE;	}	if (task_data != NULL && task_data->max_files != max_files) {	    /* fix our own iff we have one */	    if ((tdp = (struct task_data *)		 realloc(task_data, sizeof(struct task_data) +			 max_files*sizeof(FILE *))) != NULL) {		task_data = tdp;		for (i = task_data->max_files; i < max_files; i++)		    task_data->open_fps[i] = NULL;		task_data->max_files = max_files;	    }	}	/* Make sure taskVariables are deleted AFTER our hook is run. */	taskVarInit();	if(taskDeleteHookAdd((FUNCPTR)save_reclaim) != OK) {	    fprintf(stderr, 		    "Panic: taskDeleteHook cannot be added for reclaim.\n");	    return ERROR;	}	return OK;    } else 	return ERROR;}/* N.B.!! We do *not* execute in the context of the dying task here,   but rather that of tExcTask - we do get a pointer to the task's   TCB though - this pointer is in fact also the task's ID.     */static void save_reclaim(WIND_TCB *tcbp){  int i, var, oldfd;  struct task_data *tdp;  struct mall_data *mdp, *mdnextp;  if ((var = taskVarGet((int)tcbp, (int *)&task_data)) != ERROR &&      var != 0) {    tdp = (struct task_data *)var;    if (tdp->version == (FUNCPTR)save_reclaim) { /* Only handle our own */#ifdef DEBUG      fdprintf(2, "Reclaiming for task id 0x%x:\nFiles: ", (int)tcbp);#endif      /* Ugh! VxWorks doesn't even flush stdout/err - we need to	 get at those (which are task-private of course, i.e. we	 can't just do fflush(stdout) here) - we could be really	 pedantic and try to redefine stdout/err (which "are"	 function calls) too, snarfing the values when they are	 used - but besides the overhead this is problematic since	 they are actually #defines already... We'll peek in the	 TCB instead (no documentation of course). And of course,	 we must also meddle with the *file descriptor* indirections,	 or we'll just flush out on tExcTask's descriptors...   */      for (i = 1; i <= 2; i++) {	if (tcbp->taskStdFp[i] != NULL) {#ifdef DEBUG	  fdprintf(2, "fflush(%s) ", i == 1 ? "stdout" : "stderr");#endif	  oldfd = ioTaskStdGet(0, i);	  ioTaskStdSet(0, i, tcbp->taskStd[i]);	  fflush(tcbp->taskStdFp[i]);	  ioTaskStdSet(0, i, oldfd);	}      }      for (i = 3; i < tdp->max_files; i++) {	if (FD_ISSET(i, &tdp->open_fds)) {#ifdef DEBUG	  fdprintf(2, "close(%d) ", i);#endif	  (void) close(i);	}	if (tdp->open_fps[i] != NULL) {#ifdef DEBUG	  fdprintf(2, "fclose(%0x%x) ", (int)tdp->open_fps[i]);#endif	  (void) fclose(tdp->open_fps[i]);	}      }      i = 0;      mdp = tdp->mall_data;      while (mdp != NULL) {	mdnextp = mdp->next;	if(reclaim_free_function != NULL)	    (*reclaim_free_function)(mdp->self);	else	    free(mdp->self);	i++;	mdp = mdnextp;      }#ifdef DEBUG      fdprintf(2, "\nFreeing memory: total %d mallocs\n", i);#endif            if (tdp->delete_hook != NULL) {#ifdef DEBUG	  fdprintf(2, "Calling delete hook at 0x%08x\n", tdp->delete_hook);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?