📄 libasync.c
字号:
if(retval < first_ce->myaiocb64.aio_nbytes)#endif#else if(retval < first_ce->myaiocb.aio_nbytes)#endif { printf("aio_return error2: ret %d %d\n",retval,errno);#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode#else printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb64.aio_fildes, first_ce->myaiocb64.aio_offset, (long)(first_ce->myaiocb64.aio_buf), first_ce->myaiocb64.aio_nbytes, first_ce->myaiocb64.aio_lio_opcode#endif#else printf("aio_return error2: fd %d offset %d buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode#endif ); } if(retval > 0) {#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);#else mbcopy((char *)first_ce->myaiocb64.aio_buf,(char *)ubuffer,(size_t)retval);#endif#else mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval);#endif } first_ce->direct=0; takeoff_cache(gc,first_ce); } return((int)retval); }/************************************************************************ * This routine allocates a cache_entry. It contains the * aiocb block as well as linkage for use in the cache mechanism. * The space allocated here will be released after the cache entry * has been consumed. The routine takeoff_cache() will be called * after the data has been copied to user buffer or when the * cache is purged. The routine takeoff_cache() will also release * all memory associated with this cache entry. ************************************************************************/struct cache_ent *alloc_cache(gc,fd,offset,size,op)struct cache *gc;long long fd,size,op;off64_t offset;{ struct cache_ent *ce; long temp; ce=(struct cache_ent *)malloc((size_t)sizeof(struct cache_ent)); if(ce == (struct cache_ent *)0) { printf("Malloc failed\n"); exit(175); } bzero(ce,sizeof(struct cache_ent));#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off64_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; if(ce->myaiocb.aio_buf == 0)#else ce->myaiocb64.aio_fildes=(int)fd; ce->myaiocb64.aio_offset=(off64_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb64.aio_buf=(volatile void *)temp; if(ce->myaiocb64.aio_buf == 0)#endif#else ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; if(ce->myaiocb.aio_buf == 0)#endif { printf("Malloc failed\n"); exit(176); } /*bzero(ce->myaiocb.aio_buf,(size_t)size);*/#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->myaiocb.aio_reqprio=0; ce->myaiocb.aio_nbytes=(size_t)size; ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb.aio_lio_opcode=(int)op;#else ce->myaiocb64.aio_reqprio=0; ce->myaiocb64.aio_nbytes=(size_t)size; ce->myaiocb64.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb64.aio_lio_opcode=(int)op;#endif#else ce->myaiocb.aio_reqprio=0; ce->myaiocb.aio_nbytes=(size_t)size; ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb.aio_lio_opcode=(int)op;#endif ce->fd=(int)fd; ce->forward=0; ce->back=gc->tail; if(gc->tail) gc->tail->forward = ce; gc->tail= ce; if(!gc->head) gc->head=ce; gc->count++; return(ce);}/************************************************************************ * This routine checks to see if the requested data is in the * cache. *************************************************************************/struct cache_ent *incache(gc,fd,offset,size)struct cache *gc;long long fd,size;off64_t offset;{ struct cache_ent *move; if(gc->head==0) { return(0); } move=gc->head;#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while(move) { if((move->fd == fd) && (move->myaiocb.aio_offset==(off64_t)offset) && ((size_t)size==move->myaiocb.aio_nbytes)) { return(move); } move=move->forward; }#else while(move) { if((move->fd == fd) && (move->myaiocb64.aio_offset==(off64_t)offset) && ((size_t)size==move->myaiocb64.aio_nbytes)) { return(move); } move=move->forward; }#endif#else while(move) { if((move->fd == fd) && (move->myaiocb.aio_offset==(off_t)offset) && ((size_t)size==move->myaiocb.aio_nbytes)) { return(move); } move=move->forward; }#endif return(0);}/************************************************************************ * This routine removes a specific cache entry from the cache, and * releases all memory associated witht the cache entry (if not direct).*************************************************************************/voidtakeoff_cache(gc,ce)struct cache *gc;struct cache_ent *ce;{ struct cache_ent *move; long long found; move=gc->head; if(move==ce) /* Head of list */ { gc->head=ce->forward; if(gc->head) gc->head->back=0; else gc->tail = 0; if(!ce->direct) { free((void *)(ce->real_address)); free((void *)ce); } gc->count--; return; } found=0; while(move) { if(move==ce) { if(move->forward) { move->forward->back=move->back; } if(move->back) { move->back->forward=move->forward; } found=1; break; } else { move=move->forward; } } if(gc->head == ce) gc->tail = ce; if(!found) printf("Internal Error in takeoff cache\n"); move=gc->head; if(!ce->direct) { free((void *)(ce->real_address)); free((void *)ce); } gc->count--;}/************************************************************************ * This routine is used to purge the entire cache. This is called when * the cache contains data but the incomming read was not able to * be satisfied from the cache. This indicates that the previous * async read-ahead was not correct and a new pattern is emerging. ************************************************************************/voiddel_cache(gc)struct cache *gc;{ struct cache_ent *ce; ssize_t ret; ce=gc->head; while(1) { ce=gc->head; if(ce==0) return;#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED)#else while((ret = aio_cancel64(0,&ce->myaiocb64))==AIO_NOTCANCELED)#endif#else while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED)#endif ; #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret = aio_return(&ce->myaiocb);#else ret = aio_return64(&ce->myaiocb64);#endif#else ret = aio_return(&ce->myaiocb);#endif ce->direct=0; takeoff_cache(gc,ce); /* remove from cache */ }}/************************************************************************ * Like its sister async_read() this function performs async I/O for * all buffers but it differs in that it expects the caller to * request a pointer to the data to be returned instead of handing * the function a location to put the data. This will allow the * async I/O to be performed and does not require any bcopy to be * done to put the data back into the location specified by the caller. ************************************************************************/intasync_read_no_copy(gc, fd, ubuffer, offset, size, stride, max, depth)struct cache *gc;long long fd;char **ubuffer;off64_t offset;long long size;long long stride;off64_t max;long long depth;{ off64_t a_offset,r_offset; long long a_size; struct cache_ent *ce,*first_ce=0; long long i; ssize_t retval=0; ssize_t ret; long long del_read=0; long long start=0; a_offset=offset; a_size = size; /* * Check to see if it can be completed from the cache */ if((ce=(struct cache_ent *)incache(gc,fd,offset,size))) {#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) { async_suspend(ce); }#else while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS) { async_suspend(ce); }#endif#else while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) { async_suspend(ce); }#endif if(ret) printf("aio_error 3: ret %d %d\n",ret,errno);#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(ce->oldbuf != ce->myaiocb.aio_buf || ce->oldfd != ce->myaiocb.aio_fildes || ce->oldsize != ce->myaiocb.aio_nbytes) #else if(ce->oldbuf != ce->myaiocb64.aio_buf || ce->oldfd != ce->myaiocb64.aio_fildes || ce->oldsize != ce->myaiocb64.aio_nbytes) #endif#else if(ce->oldbuf != ce->myaiocb.aio_buf || ce->oldfd != ce->myaiocb.aio_fildes || ce->oldsize != ce->myaiocb.aio_nbytes) #endif printf("It changed in flight\n"); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ retval=aio_return(&ce->myaiocb);#else retval=aio_return64(&ce->myaiocb64);#endif#else retval=aio_return(&ce->myaiocb);#endif if(retval > 0) {#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ *ubuffer=(char *)ce->myaiocb.aio_buf;#else *ubuffer=(char *)ce->myaiocb64.aio_buf;#endif#else *ubuffer=(char *)ce->myaiocb.aio_buf;#endif }else *ubuffer=0;#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(retval < ce->myaiocb.aio_nbytes)#else if(retval < ce->myaiocb64.aio_nbytes)#endif#else if(retval < ce->myaiocb.aio_nbytes)#endif { printf("aio_return error4: ret %d %d\n",retval,errno);#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode#else printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n", ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, (long)(ce->myaiocb64.aio_buf), ce->myaiocb64.aio_nbytes, ce->myaiocb64.aio_lio_opcode#endif#else printf("aio_return error4: fd %d offset %d buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode#endif ); } ce->direct=1; takeoff_cache(gc,ce); /* do not delete buffer*/ putoninuse(gc,ce); }else { /* * Clear the cache and issue the first request async() */ del_cache(gc); del_read++; first_ce=alloc_cache(gc,fd,offset,size,(long long)LIO_READ); /* allocate buffer */ /*printf("allocated buffer/read %x offset %d\n",first_ce->myaiocb.aio_buf,offset);*/again:#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ first_ce->oldbuf=first_ce->myaiocb.aio_buf; first_ce->oldfd=first_ce->myaiocb.aio_fildes; first_ce->oldsize=first_ce->myaiocb.aio_nbytes; ret=aio_read(&first_ce->myaiocb);#else first_ce->oldbuf=first_ce->myaiocb64.aio_buf; first_ce->oldfd=first_ce->myaiocb64.aio_fildes; first_ce->oldsize=first_ce->myaiocb64.aio_nbytes; ret=aio_read64(&first_ce->myaiocb64);#endif#else first_ce->oldbuf=first_ce->myaiocb.aio_buf; first_ce->oldfd=first_ce->myaiocb.aio_fildes; first_ce->oldsize=first_ce->myaiocb.aio_nbytes; ret=aio_read(&first_ce->myaiocb);#endif if(ret!=0) { if(errno==EAGAIN) goto again; else printf("error returned from aio_read(). Ret %d errno %d\n",ret,errno); } } if(stride==0) /* User does not want read-ahead */ goto out; if(a_offset<0) /* Before beginning of file */ goto out; if(a_offset+size>max) /* After end of file */ goto out; if(depth >=(max_depth-1)) depth=max_depth-1; if(depth==0) goto out; if(gc->count > 1) start=depth-1; for(i=start;i<depth;i++) /* Issue read-aheads for the depth specified */ { r_offset=a_offset+((i+1)*(stride*a_size)); if(r_offset<0) continue; if(r_offset+size > max) continue; if((ce=incache(gc,fd,r_offset,a_size))) continue; ce=alloc_cache(gc,fd,r_offset,a_size,(long long)LIO_READ);#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->oldbuf=ce->myaiocb.aio_buf; ce->oldfd=ce->myaiocb.aio_fildes; ce->oldsize=ce->myaiocb.aio_nbytes; ret=aio_read(&ce->myaiocb);#else ce->oldbuf=ce->myaiocb64.aio_buf; ce->oldfd=ce->myaiocb64.aio_fildes; ce->oldsize=ce->myaiocb64.aio_nbytes; ret=aio_read64(&ce->myaiocb64);#endif#else ce->oldbuf=ce->myaiocb.aio_buf; ce->oldfd=ce->myaiocb.aio_fildes; ce->oldsize=ce->myaiocb.aio_nbytes; ret=aio_read(&ce->myaiocb);#endif if(ret!=0) { takeoff_cache(gc,ce); break; } } out: if(del_read) /* Wait for the first read to complete */ {#ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) { async_suspend(first_ce); }#else while((ret=aio_error64(&first_ce->myaiocb64))== EINPROGRESS) { async_suspend(first_ce); }#endif#else while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) { async_suspend(first_ce); }#endif if(ret) printf("aio_error 4: ret %d %d\n",ret,errno);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -