mpool.libtp

来自「基于组件方式开发操作系统的OSKIT源代码」· LIBTP 代码 · 共 747 行 · 第 1/2 页

LIBTP
747
字号
/******************************************************************************VERSION $Id: mpool.libtp,v 1.3 1997/02/22 14:57:55 peter Exp $PACKAGE: 	User Level Shared Memory ManagerDESCRIPTION: 		This package provides a buffer pool interface implemented as	a collection of file pages mapped into shared memory.	Based on Mark's buffer managerROUTINES:     External	buf_alloc	buf_flags	buf_get	buf_init	buf_last	buf_open	buf_pin	buf_sync	buf_unpin    Internal	bf_assign_buf	bf_fid_to_fd	bf_newbuf	bf_put_page	******************************************************************************/#include	<sys/types.h>#include	<assert.h>#include	<sys/file.h>#include	<sys/stat.h>#include	<stdio.h>#include	<errno.h>#include	"list.h"#include	"user.h"#include	"txn_sys.h"#include	"buf.h"#include	"semkeys.h"#include	"error.h"/*    we need to translate between some type of file id that the user     process passes and a file descriptor.  For now, it's a nop.*/#define GET_MASTER      get_sem ( buf_spinlock )#define RELEASE_MASTER  release_sem ( buf_spinlock )#define	LRUID	*buf_lru#define	LRUP	(bufhdr_table+*buf_lru)#define	MRU	bufhdr_table[*buf_lru].lru.prev/* Global indicator that you have started reusing buffers */int	do_statistics = 0;/*    Process Statics (pointers into shared memory)*/static	BUF_T	*buf_table = 0;static	BUFHDR_T	*bufhdr_table;static	int	*buf_hash_table;static	int	*buf_lru;		/* LRU is the free list */static	int	buf_spinlock;static	FINFO_T	*buf_fids;static	int	*buf_sp;		/* Pointer to string free space */static	char	*buf_strings;/* Process Local FID->FD table */static	int	fds[NUM_FILE_ENTRIES];/* Static routines */static	BUFHDR_T	*bf_assign_buf();static	int		bf_fid_to_fd();static	BUFHDR_T	*bf_newbuf();static	int		bf_put_page();/*    Return  0 on success	    1 on failure*/extern intbuf_init ( ){    ADDR_T	buf_region;    BUFHDR_T	*bhp;    int		i;    int		ref_count;    int		*spinlockp;    /*	Initialize Process local structures    */    for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {	fds[i] = -1;    }    buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM,				 BUF_REGION_SIZE, &ref_count );    if ( !buf_region ) {	return (1);    }    error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region,		    BUF_REGION_NUM, BUF_REGION_SIZE );    buf_table = (BUF_T *)buf_region;    bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS);    buf_hash_table = (int *)(bufhdr_table + NUM_BUFS);    buf_lru = buf_hash_table + NUMTABLE_ENTRIES;    spinlockp = buf_lru + 1;    buf_fids = (FINFO_T *)(spinlockp+1);    buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES);    buf_strings = (char *)(buf_sp + 1);    /* Create locking spinlock (gets creating holding the lock) */    buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 );    if ( buf_spinlock < 0 )  {	return(1);    }    if ( ref_count <= 1 ) {	*spinlockp = buf_spinlock;	/* Now initialize the buffer manager */	/* 1. Free list */	*buf_lru = 0;	/* 2. Buffer headers */	for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) {		bhp->lru.next = i+1;		bhp->lru.prev = i-1;		bhp->flags = 0;				/* All Flags off */		bhp->refcount = 0;		bhp->wait_proc = -1;			/* No sleepers */		LISTPE_INIT ( hash, bhp, i );		/* Hash chains */	}	bufhdr_table[0].lru.prev = NUM_BUFS-1;	bufhdr_table[NUM_BUFS-1].lru.next = 0;	/* 3. Hash Table */	for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) {		buf_hash_table[i] = NUM_BUFS;	}	/* 4. File ID Table */	for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {		buf_fids[i].offset = -1;		buf_fids[i].npages = -1;		buf_fids[i].refcount = 0;	}	/* 5. Free String Pointer */	*buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES);	if (RELEASE_MASTER) {		return(1);	}	error_log0 ( "Initialized buffer region\n" );    }     return (0);}extern	voidbuf_exit(){    int	ref;    int	i;    /* Flush Buffer Pool on Exit */    for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {	if ( fds[i] != -1 ) {		close ( fds[i] );	}    }    if ( buf_table ) {	detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref );    }    return;}/*	We need an empty buffer.  Find the LRU unpinned NON-Dirty page.*/static BUFHDR_T	*bf_newbuf(){    int		fd;    int		lruid;    int		nbytes;    int		ndx;    BUFHDR_T	*bhp;    lruid = LRUID;    for ( bhp = LRUP; 	  bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS); 	  bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) {	if ( bhp->lru.next == lruid ) {		/* OUT OF BUFFERS */		error_log1 ( "All buffers are pinned.  %s\n",				"Unable to grant buffer request" );		return(NULL);	}    }    /* BHP can be used */    if ( bhp->flags & BUF_DIRTY ) {	do_statistics = 1;	/* 	    MIS  Check for log flushed appropriately	*/	fd = bf_fid_to_fd(bhp->id.file_id);	if ( fd == -1 ) {	    error_log1 ("Invalid fid %d\n", bhp->id.file_id);	    return(NULL);	}	if ( bf_put_page(fd, bhp) < 0 ) {	    return(NULL);	}    }    /* Update Hash Pointers */    ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id );    LISTP_REMOVE(bufhdr_table, hash, bhp);    if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) {	if ( bhp->hash.next != (bhp-bufhdr_table) ) {		buf_hash_table[ndx] = bhp->hash.next;	} else {		buf_hash_table[ndx] = NUM_BUFS;	}    }    INIT_BUF(bhp);     return(bhp);}/*    buf_alloc    Add a page to a file and return a buffer for it.*/ADDR_Tbuf_alloc ( fid, new_pageno )int	fid;int	*new_pageno;{	BUFHDR_T	*bhp;	int	fd;	int	len;	int	ndx;	OBJ_T	fobj;	if (GET_MASTER) {		return(NULL);	}	if ( buf_fids[fid].npages == -1 ) {	    /* initialize npages field */	    fd = bf_fid_to_fd ( fid );	}	assert (fid < NUM_FILE_ENTRIES);	*new_pageno = buf_fids[fid].npages;	if ( *new_pageno == -1 ) {	    RELEASE_MASTER;	    return ( NULL );	}	buf_fids[fid].npages++;	ndx = BUF_HASH ( fid, *new_pageno );	fobj.file_id = fid;	fobj.obj_id  = *new_pageno;	bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len );	if ( RELEASE_MASTER ) {		/* Memory leak */		return(NULL);	}	if ( bhp ) {	    return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));	} else {	    return ( NULL );	}}/*	Buffer Flags	BF_DIRTY		Mark page as dirty	BF_EMPTY		Don't initialize page, just get buffer	BF_PIN			Retrieve with pin MISMight want to add a flag that sets an LSN for this buffer is theDIRTY flag is setEventually, you may want a flag that indicates the I/O and lockrequest should be shipped off together, but not for now.*/extern ADDR_Tbuf_get ( file_id, page_id, flags, len )int	file_id;int	page_id;u_long	flags;int	*len;		/* Number of bytes read into buffer */{	BUFHDR_T	*bhp;	int		bufid;	int		fd;	int		ndx;	int		next_bufid;	int		stat;	OBJ_T		fobj;		ndx = BUF_HASH ( file_id, page_id );	fobj.file_id = (long) file_id;	fobj.obj_id = (long) page_id;	if ( GET_MASTER ) {		return(NULL);	}	/*		This could be a for loop, but we lose speed		by making all the cases general purpose so we		optimize for the no-collision case. 	*/	bufid = buf_hash_table[ndx]; 	if ( bufid < NUM_BUFS ) {	    for ( bhp = bufhdr_table+bufid; 		  !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID);		  bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) {		if ( bhp->hash.next == bufid ) {		    goto not_found;		}	    }/* found */	    if ( flags & BF_PIN ) {		    bhp->flags |= BUF_PINNED;		    bhp->refcount++;#ifdef PIN_DEBUG	fprintf(stderr, "buf_get: %X PINNED (%d)\n", 			buf_table + (bhp-bufhdr_table), bhp->refcount);#endif	    }	    if ( flags & BF_DIRTY ) {		    bhp->flags |= BUF_DIRTY;	    }	    while ( bhp->flags & BUF_IO_IN_PROGRESS ) {		/* MIS -- eventually err check here */#ifdef DEBUG		printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc,			my_txnp - txn_table);#endif#ifdef WAIT_STATS		buf_waits++;#endif		stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock );		if ( stat ) {			/* Memory leak */			return(NULL);		}		if (!( bhp->flags & BUF_IO_IN_PROGRESS) &&		    (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) {			if (RELEASE_MASTER)				return(NULL);			return(buf_get ( file_id, page_id, flags, len ));		}	    }	    MAKE_MRU( bhp );	    *len = BUFSIZE;	} else {not_found:	    /* If you get here, the page isn't in the hash table */	    bhp = bf_assign_buf ( ndx, &fobj, flags, len );	}	/* Common code between found and not found */	if ( bhp && bhp->flags & BUF_NEWPAGE ) {	    *len = 0;

⌨️ 快捷键说明

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