/* Copyright (c) 2001-2022, The Ohio State University. All rights * reserved. * * This file is part of the MVAPICH2 software package developed by the * team members of The Ohio State University's Network-Based Computing * Laboratory (NBCL), headed by Professor Dhabaleswar K. (DK) Panda. * * For detailed copyright and licensing information, please refer to the * copyright file COPYRIGHT in the top level MVAPICH2 directory. * */ #include #ifdef CR_AGGRE #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ib_comm.h" // #include "ibutil.h" #include "debug.h" void *ib_buffer_slot_addr(struct ib_buffer *buf, int slot) { if (slot > buf->num_slot) { error("Error!! slot %d > buf-slot %d\n", slot, buf->num_slot); return NULL; } return (buf->addr + ((unsigned long) slot) * buf->slot_size); } void dump_ib_buffer(struct ib_buffer *buf) { printf("\n=========== dump ib_buffer: %s\n", buf->name); printf("\ttotal %d slots, free-slots=%d, total size %ld, slot-size=%d\n", buf->num_slot, buf->free_slots, buf->size, buf->slot_size); printf("\tbitmap = \n"); bmp_dump(&buf->bitmap); printf("\n==============================\n"); } struct ib_buffer *create_ib_buffer(int size, int slot_size, char *name) { int i; struct ib_buffer *buf = malloc(sizeof(struct ib_buffer)); memset(buf, 0, sizeof(struct ib_buffer)); buf->size = size; buf->slot_size = slot_size; buf->num_slot = size / slot_size; // num_slot; buf->free_slots = buf->num_slot; // alloc actual mem for this buf buf->addr = memalign(PAGE_SIZE, size); // init the bitmap for this buf, all bits are inited to "1" if (bmp_init(&buf->bitmap, buf->num_slot, 1) < 0) { error("Error!: Fail to create ib_buf %s\n", name); goto err_out_1; } //memset( buf->state,SLOT_FREE, BUF_SLOT_COUNT ); // all slots are free now // init the buf-mutex pthread_mutex_init(&buf->mutex, NULL); // init locks for each slot for (i = 0; i < buf->num_slot; i++) { pthread_mutex_init(&buf->lock[i], NULL); } // init the buf_semaphore dbg("ib-buf (%s): init sem to %d\n", name, buf->num_slot); sem_init(&buf->buf_sem, 0, buf->num_slot); // init the sem-count to be 0 strcpy(buf->name, name); printf("Has created ib-buf \"%s\", size=%d, slot-size %d, %d slots \n", name, size, slot_size, buf->num_slot); return buf; err_out_1: free(buf->addr); free(buf); return NULL; } /* free all resources in this IB_buffer */ void free_ib_buffer(struct ib_buffer *buf) { int i; dbg(" ----> free buf \"%s\" \n", buf->name); sem_destroy(&buf->buf_sem); // release the mutex pthread_mutex_destroy(&buf->mutex); for (i = 0; i < buf->num_slot; i++) { pthread_mutex_destroy(&buf->lock[i]); } // destroy the bitmap bmp_destroy(&buf->bitmap); /// dereg the mem-region if (buf->mr) mpirun_ibv_ops.dereg_mr(buf->mr); free(buf->addr); free(buf); //dbg(" <----- buf %s\n", buf->name ); } /* Get a free slot in this buffer. The slot size = buf->slot_size. the address of this slot is returned via (*addr). if "expect"=1, need put a lock at the allocated slot */ int get_buf_slot(struct ib_buffer *buf, void **addr, int expect) { int i; // search_free_slot: sem_wait(&buf->buf_sem); // dec the free-slot by 1, may block here pthread_mutex_lock(&buf->mutex); /////////////// i = bmp_ffs_and_toggle(&buf->bitmap); if (i >= 0) // has grab slot i { buf->free_slots--; pthread_mutex_unlock(&buf->mutex); if (expect) pthread_mutex_lock(&buf->lock[i]); if (addr) { *addr = (buf->addr + i * buf->slot_size); } return i; } /* else{ /// this should never happen!! pthread_mutex_unlock( &buf->mutex ); error(" Error at buf-slot at %s\n", buf->name ); goto search_free_slot; } */ /////////////////// /* for(i=0; i< buf->num_slot; i++ ) { if( buf->state[i] == SLOT_FREE )// find a free slot { buf->state[i] = SLOT_INUSE; if( expect ) pthread_mutex_lock( & buf->lock[i] ); buf->free_slots--; pthread_mutex_unlock( &buf->mutex ); //dbg("get slot %d from buf \"%s\"\n", i, buf->name); if( addr ){ *addr = (buf->addr + i*buf->slot_size); } return i; } } */ pthread_mutex_unlock(&buf->mutex); error(" Error when alloc buf-slot at %s\n", buf->name); return -1; // this shouldn't happen!! } /* Free a slot, return it to buf. If "expect" =1, unlock the related mtx, to wake up any threads waiting on it */ int free_buf_slot(struct ib_buffer *buf, int slot, int expect) { pthread_mutex_lock(&buf->mutex); //buf->state[slot] = SLOT_FREE; if (bmp_get_pos(&buf->bitmap, slot) == 0) { bmp_set_bit(&buf->bitmap, slot); } else { //dbg("========= buf %p: slot %d already free...\n", buf, slot); } buf->free_slots++; //////////// if (expect) pthread_mutex_unlock(&buf->lock[slot]); pthread_mutex_unlock(&buf->mutex); sem_post(&buf->buf_sem); // increase the slot-count by 1 //dbg("Has freed \"%s\" slot %d\n", buf->name, slot); return 0; } #endif