bool deq_rec::rcv_decode(rec_hdr_t h, std::ifstream* ifsp, std::size_t& rec_offs) { if (rec_offs == 0) { //_deq_hdr.hdr_copy(h); ::rec_hdr_copy(&_deq_hdr._rhdr, &h); ifsp->read((char*)&_deq_hdr._deq_rid, sizeof(uint64_t)); ifsp->read((char*)&_deq_hdr._xidsize, sizeof(std::size_t)); #if defined(JRNL_32_BIT) ifsp->ignore(sizeof(uint32_t)); // _filler0 #endif rec_offs = sizeof(_deq_hdr); // Read header, allocate (if req'd) for xid if (_deq_hdr._xidsize) { _buff = std::malloc(_deq_hdr._xidsize); MALLOC_CHK(_buff, "_buff", "enq_rec", "rcv_decode"); } } if (rec_offs < sizeof(_deq_hdr) + _deq_hdr._xidsize) { // Read xid (or continue reading xid) std::size_t offs = rec_offs - sizeof(_deq_hdr); ifsp->read((char*)_buff + offs, _deq_hdr._xidsize - offs); std::size_t size_read = ifsp->gcount(); rec_offs += size_read; if (size_read < _deq_hdr._xidsize - offs) { assert(ifsp->eof()); // As we may have read past eof, turn off fail bit ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); assert(!ifsp->fail() && !ifsp->bad()); return false; } } if (rec_offs < sizeof(_deq_hdr) + (_deq_hdr._xidsize ? _deq_hdr._xidsize + sizeof(rec_tail_t) : 0)) { // Read tail (or continue reading tail) std::size_t offs = rec_offs - sizeof(_deq_hdr) - _deq_hdr._xidsize; ifsp->read((char*)&_deq_tail + offs, sizeof(rec_tail_t) - offs); std::size_t size_read = ifsp->gcount(); rec_offs += size_read; if (size_read < sizeof(rec_tail_t) - offs) { assert(ifsp->eof()); // As we may have read past eof, turn off fail bit ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); assert(!ifsp->fail() && !ifsp->bad()); return false; } } ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size()); if (_deq_hdr._xidsize) chk_tail(); // Throws if tail invalid or record incomplete assert(!ifsp->fail() && !ifsp->bad()); return true; }
void pmgr::initialize(aio_callback* const cbp, const uint32_t cache_pgsize_sblks, const uint16_t cache_num_pages) { // As static use of this class keeps old values around, clean up first... pmgr::clean(); _pg_index = 0; _pg_cntr = 0; _pg_offset_dblks = 0; _aio_evt_rem = 0; _cache_pgsize_sblks = cache_pgsize_sblks; _cache_num_pages = cache_num_pages; _cbp = cbp; // 1. Allocate page memory (as a single block) std::size_t cache_pgsize = _cache_num_pages * _cache_pgsize_sblks * _sblkSizeBytes; if (::posix_memalign(&_page_base_ptr, QLS_AIO_ALIGN_BOUNDARY_BYTES, cache_pgsize)) { clean(); std::ostringstream oss; oss << "posix_memalign(): alignment=" << QLS_AIO_ALIGN_BOUNDARY_BYTES << " size=" << cache_pgsize; oss << FORMAT_SYSERR(errno); throw jexception(jerrno::JERR__MALLOC, oss.str(), "pmgr", "initialize"); } // 2. Allocate array of page pointers _page_ptr_arr = (void**)std::malloc(_cache_num_pages * sizeof(void*)); MALLOC_CHK(_page_ptr_arr, "_page_ptr_arr", "pmgr", "initialize"); // 3. Allocate and initialize page control block (page_cb) array _page_cb_arr = (page_cb*)std::malloc(_cache_num_pages * sizeof(page_cb)); MALLOC_CHK(_page_cb_arr, "_page_cb_arr", "pmgr", "initialize"); std::memset(_page_cb_arr, 0, _cache_num_pages * sizeof(page_cb)); // 4. Allocate IO control block (iocb) array _aio_cb_arr = (aio_cb*)std::malloc(_cache_num_pages * sizeof(aio_cb)); MALLOC_CHK(_aio_cb_arr, "_aio_cb_arr", "pmgr", "initialize"); // 5. Set page pointers in _page_ptr_arr, _page_cb_arr and iocbs to pages within page block for (uint16_t i=0; i<_cache_num_pages; i++) { _page_ptr_arr[i] = (void*)((char*)_page_base_ptr + _cache_pgsize_sblks * _sblkSizeBytes * i); _page_cb_arr[i]._index = i; _page_cb_arr[i]._state = UNUSED; _page_cb_arr[i]._pbuff = _page_ptr_arr[i]; _page_cb_arr[i]._pdtokl = new std::deque<data_tok*>; _page_cb_arr[i]._pdtokl->clear(); _aio_cb_arr[i].data = (void*)&_page_cb_arr[i]; } // 6. Allocate io_event array, max one event per cache page plus one for each file const uint16_t max_aio_evts = _cache_num_pages + 1; // One additional event for file header writes _aio_event_arr = (aio_event*)std::malloc(max_aio_evts * sizeof(aio_event)); MALLOC_CHK(_aio_event_arr, "_aio_event_arr", "pmgr", "initialize"); // 7. Initialize AIO context if (int ret = aio::queue_init(max_aio_evts, &_ioctx)) { std::ostringstream oss; oss << "io_queue_init() failed: " << FORMAT_SYSERR(-ret); throw jexception(jerrno::JERR__AIO, oss.str(), "pmgr", "initialize"); } }
/** Link the given file into flash ROM. * \param programfile Filename containing program to load * \param symtabfile File containing the symbol table of the kernel * \param process Output for storing pointer to process structure * of program * \return 0 on success, 1 if file was damaged or not found, 2 if not * enough memory, 3 if symbol could not be resolved */ uint_fast8_t minilink_load(const char *programfile, const char *symtabfile, struct process ***proclist) { Minilink_Header mlhdr; uint16_t *symvalp = NULL; Minilink_ProgramInfoHeader pihdr, *instprog; int status = 1; struct io_buf_st buf_ml; struct io_buf_st buf_sym; #if DEBUG_DIFF void * memblock; memblock = malloc(node_id * 40); #endif LEDGOFF; LEDBOFF; LEDRON; memset(&pihdr, 0, sizeof(pihdr)); if (strlen(programfile) > MINILINK_MAX_FILENAME - 1) { DPUTS("Name too long.\n"); return 1; } buf_ml.filled = 0; buf_ml.pos = 0; LEDBON; buf_ml.fd = cfs_open(programfile, CFS_READ); if (buf_ml.fd < 0) { DPUTS("Could not open File."); goto cleanup; } buf_sym.pos = 0; buf_sym.filled = 0; buf_sym.fd = cfs_open(symtabfile, CFS_READ); LEDBOFF; //Check whether the files are ok if (ml_file_check(buf_ml.fd, MINILINK_PGM_MAGIC) != 1) { DPUTS("Ret is not 1\n"); return 1; } if (ml_file_check(buf_sym.fd, MINILINK_SYM_MAGIC) != 1) { DPUTS("Ret is not 1\n"); return 1; } LEDGON; //Reset cfs_seek(buf_ml.fd, 0, CFS_SEEK_SET); cfs_seek(buf_sym.fd, 0, CFS_SEEK_SET); LEDBON; //Read header, but do not write to buffer! if (cfs_read(buf_ml.fd, &mlhdr, sizeof(mlhdr)) != sizeof(mlhdr)) { DPUTS("Could not Read Header."); goto cleanup; } //Now let's get the ram for the symbol table symvalp = malloc(mlhdr.symentries * sizeof(uint16_t)); if (symvalp == NULL) { DPUTS("Could not allocate memory for symtbl."); status = 2; goto cleanup; } //------------ Resolve the symbol-list. - This must be done anyway { uint16_t symctr; char cursym[MINILINK_MAX_SYMLEN]; uint16_t curr_add = 0; cursym[0] = 0; if (buf_sym.fd < 0) { DPUTS("Could not open File."); goto cleanup; } { //get rid of the header. uint8_t shift = sizeof(Minilink_SymbolHeader); while (shift) { shift_iobuf(&buf_sym); buf_sym.pos = Min(buf_sym.filled, shift); shift -= buf_sym.pos; } } //Fill Buffer..... shift_iobuf(&buf_sym); #define NEXTSYMPOS {buf_sym.pos++; if(buf_sym.filled == buf_sym.pos) shift_iobuf(&buf_sym);} for (symctr = 0; symctr < mlhdr.symentries; symctr++) { uint8_t samechars; //fill buffer. shift_iobuf(&buf_ml); samechars = buf_ml.data[buf_ml.pos]; buf_ml.pos++; DPRINTF("Looking up: <%i>%s\n", samechars, &(buf_ml.data[buf_ml.pos])); while (1) { /// \fixme make sure we don't go past the buffer // The next code is a bit complicated, I'll add some graphix to visualize it /// \todo Grafiken erstellen. //get next symbol uint8_t symattr; uint16_t sym_write_pos; symattr = buf_sym.data[buf_sym.pos]; NEXTSYMPOS; sym_write_pos = symattr & 0x3F; if (samechars > sym_write_pos) { //Ok, looks like we went past the symbol DPUTS("Symbol could not be resolved - past same\n"); status = 1; goto cleanup; } else if (samechars == sym_write_pos) { while (1) { //Loop until we reach the Null-char if (buf_sym.data[buf_sym.pos] != buf_ml.data[buf_ml.pos]) break; if (buf_ml.data[buf_ml.pos] == '\0') { DPUTS("FOUND!\n"); break; //Could take any of the two, as they are the same } //It is important that this comes afterwards! - It must point at the NULL NEXTSYMPOS; buf_ml.pos++; samechars++; } if (buf_sym.data[buf_sym.pos] > buf_ml.data[buf_ml.pos]) { // We are searching for a symbol smaller then // the current on. - They are sorted, therefore we will not find it anymore DPUTS("Symbol could not be resolved - past alpha\n"); status = 3; goto cleanup; } } while (buf_sym.data[buf_sym.pos] != '\0') NEXTSYMPOS; NEXTSYMPOS; //one more! symattr &= 0xC0; symattr >>= 6; switch (symattr) { case 0: CPY16(curr_add, buf_sym.data[buf_sym.pos]); NEXTSYMPOS; break; case 1: curr_add--; curr_add -= buf_sym.data[buf_sym.pos]; break; case 3: curr_add += 0x0100; case 2: curr_add += buf_sym.data[buf_sym.pos]; break; } NEXTSYMPOS; //DPRINTF("Checking: %i:%s - %x same: %i\n",buf_sym.data[0] & 0x3F , &(buf_sym.data[1]), curr_add, samechars); //We've found the symbol, so let's break if (buf_ml.data[buf_ml.pos] == '\0') { //Move on to next symbol. buf_ml.pos++; break; } } //Loop searching for the symbol ((uint16_t *) (symvalp))[symctr] = curr_add; //copy the symbol address to memory MALLOC_CHK(symvalp); } //Loop looping through symbols } // End of resolving symbol list. #undef NEXTSYMPOS LEDGOFF; pihdr.magic = MINILINK_INST_MAGIC; pihdr.crc = mlhdr.common.crc; //pihdr.mem[DATA].ptr = NULL; pihdr.mem[MINILINK_DATA].size = mlhdr.datasize; //pihdr.mem[MINILINK_BSS].ptr = NULL; pihdr.mem[MINILINK_BSS].size = mlhdr.bsssize; //pihdr.mem[MINILINK_MIG].ptr = NULL; pihdr.mem[MINILINK_MIG].size = mlhdr.migsize; //pihdr.mem[MINILINK_MIGPTR].ptr = NULL; pihdr.mem[MINILINK_MIGPTR].size = mlhdr.migptrsize; //pihdr.process = NULL; pihdr.mem[MINILINK_TEXT].size = mlhdr.textsize; strncpy(pihdr.sourcefile, programfile, MINILINK_MAX_FILENAME); //Let's see whether the program is already installed instprog = program_already_loaded(&pihdr); if (instprog != NULL) { struct process * curproc; /* Check if program to be reloaded has active processes, i.e. appears * in the process list */ for (curproc = process_list; curproc != NULL; curproc = curproc->next) { if ((uintptr_t) (void*) curproc >= (uintptr_t)(instprog->mem[MINILINK_DATA].ptr) && (uintptr_t) (void*) curproc < (uintptr_t)(instprog->mem[MINILINK_DATA].ptr + instprog->mem[MINILINK_DATA].size)) { puts("Process in use. Can't install."); status = 2; goto cleanup; } } DPRINTF("Loading header from %x\n Data: %x\nBss: %x\n", (uint16_t ) instprog, (uint16_t)instprog->mem[MINILINK_DATA].ptr, (uint16_t)instprog->mem[MINILINK_BSS].ptr); memcpy(&pihdr, instprog, sizeof(pihdr)); DPRINTF("After copy:\n Data: %x\nBss: %x\n", (uint16_t)(pihdr.mem[MINILINK_DATA].ptr), (uint16_t)pihdr.mem[MINILINK_BSS].ptr); pihdr.mem[MINILINK_TEXT].ptr = (uint8_t *) instprog + sizeof(pihdr); } else { //Process does not exist, let's get some memory for linking it status = 2; uint8_t ctr; //Now let's allocate Memory if ((mlhdr.textsize & 1) || (mlhdr.datasize & 1) || (mlhdr.bsssize & 1)) { DPUTS(".data, .bss or .text section not word aligned"); goto cleanup; } pihdr.mem[MINILINK_TEXT].ptr = ml_alloc_text(pihdr.mem[MINILINK_TEXT].size + sizeof(pihdr)); if (pihdr.mem[MINILINK_TEXT].ptr == NULL) { DPUTS("Could not alloc Text."); goto cleanup; } pihdr.mem[MINILINK_TEXT].ptr += sizeof(pihdr); //Allocate Memory; Starting beheind text for (ctr = MINILINK_DATA; ctr < MINILINK_SEC; ctr++) { if (pihdr.mem[ctr].size) { pihdr.mem[ctr].ptr = ml_alloc_mem(mlhdr.datasize); if (pihdr.mem[ctr].ptr == NULL) { DPRINTF("Could not alloc Memory for %i\n", ctr); goto cleanup; } } } pihdr.process = pihdr.mem[MINILINK_TEXT].ptr + mlhdr.processoffset; DPRINTF("PO: %.4x = %.4x + %.4x\n", (uintptr_t )pihdr.process, (uintptr_t)pihdr.mem[MINILINK_TEXT].ptr, mlhdr.processoffset); } // Build up array where to place what.... { uint8_t r; for (r = 0; r < MINILINK_SEC; r++) { DPRINTF("%x len: %x\n", (uintptr_t)(pihdr.mem[r].ptr), (uintptr_t)(pihdr.mem[r].size)); } } LEDBOFF; // Link data section DPRINTF("\n\nRelocating DATA to %x len: %x\n", (uint16_t)pihdr.mem[MINILINK_DATA].ptr, (uint16_t)pihdr.mem[MINILINK_DATA].size); status = ml_relocate(&buf_ml, pihdr.mem[MINILINK_DATA].size, pihdr.mem[MINILINK_DATA].ptr, symvalp, mlhdr.symentries, &pihdr, NULL); if (status != 0) goto cleanup; MALLOC_CHK(symvalp); // Link mig section if (mlhdr.migsize) { DPRINTF("\n\nRelocating MIG to %x len: %x\n", (uint16_t)pihdr.mem[MINILINK_MIG].ptr, (uint16_t)pihdr.mem[MINILINK_MIG].size); status = ml_relocate(&buf_ml, pihdr.mem[MINILINK_MIG].size, pihdr.mem[MINILINK_MIG].ptr, symvalp, mlhdr.symentries, &pihdr, NULL); if (status != 0) goto cleanup; } MALLOC_CHK(symvalp); // Link migptr section if (mlhdr.migptrsize) { DPRINTF("\n\nRelocating MIG to %x len: %x\n", (uint16_t)pihdr.mem[MINILINK_MIGPTR].ptr, (uint16_t)pihdr.mem[MINILINK_MIGPTR].size); status = ml_relocate(&buf_ml, pihdr.mem[MINILINK_MIGPTR].size, pihdr.mem[MINILINK_MIGPTR].ptr, symvalp, mlhdr.symentries, &pihdr, NULL); if (status != 0) goto cleanup; } MALLOC_CHK(symvalp); //Set Bss to 0 if (mlhdr.bsssize) { DPRINTF("\n\nClearing BSS at %x\n", (uint16_t) pihdr.mem[MINILINK_BSS].ptr); memset(pihdr.mem[MINILINK_BSS].ptr, 0, pihdr.mem[MINILINK_BSS].size); } LEDGON; if (instprog == NULL) { DPRINTF("\n\nRelocating ROM to %x len: %x\n", (uint16_t) pihdr.mem[MINILINK_TEXT].ptr, (uint16_t ) mlhdr.textsize); //Buf ML is positioned behind the symbol table status = ml_relocate(&buf_ml, mlhdr.textsize, pihdr.mem[MINILINK_TEXT].ptr, symvalp, mlhdr.symentries, &pihdr, &memwrite_flash); if (status != 0) goto cleanup; MALLOC_CHK(symvalp); DPRINTF("\n\nWriting header to %x\n", (uint16_t)pihdr.mem[MINILINK_TEXT].ptr - sizeof(pihdr)); memwrite_flash(pihdr.mem[MINILINK_TEXT].ptr - sizeof(pihdr), &pihdr, sizeof(pihdr)); //if(memcmp(pTxt - sizeof(pihdr), &pihdr, sizeof(pihdr)) != 0) printf("\n\nPANIC!!!\n\n"); { Minilink_ProgramInfoHeader *tmp, *tmp2; tmp2 = &pihdr; tmp = pihdr.mem[MINILINK_TEXT].ptr - sizeof(pihdr); //printf("PIHproc: %x - %x\n", (uint16_t)(tmp->process), (uint16_t)(tmp2->process)); } if (status != 0) goto cleanup; } LEDROFF; LEDGOFF; *proclist = pihdr.process; DPUTS("Loading complete."); cleanup: #if DEBUG_DIFF free(memblock); #endif free(symvalp); cfs_close(buf_ml.fd); cfs_close(buf_sym.fd); if (status != 0) { uint8_t ctr; //No flash for (ctr = 1; ctr < MINILINK_SEC; ctr++) { ml_free_mem(pihdr.mem[ctr].ptr); } } return status; }
uint32_t deq_rec::decode(rec_hdr_t& h, void* rptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks) { assert(rptr != 0); assert(max_size_dblks > 0); std::size_t rd_cnt = 0; if (rec_offs_dblks) // Continuation of record on new page { const uint32_t hdr_xid_dblks = size_dblks(sizeof(deq_hdr_t) + _deq_hdr._xidsize); const uint32_t hdr_xid_tail_dblks = size_dblks(sizeof(deq_hdr_t) + _deq_hdr._xidsize + sizeof(rec_tail_t)); const std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; if (hdr_xid_tail_dblks - rec_offs_dblks <= max_size_dblks) { // Remainder of xid fits within this page if (rec_offs - sizeof(deq_hdr_t) < _deq_hdr._xidsize) { // Part of xid still outstanding, copy remainder of xid and tail const std::size_t xid_offs = rec_offs - sizeof(deq_hdr_t); const std::size_t xid_rem = _deq_hdr._xidsize - xid_offs; std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); rd_cnt = xid_rem; std::memcpy((void*)&_deq_tail, ((char*)rptr + rd_cnt), sizeof(_deq_tail)); chk_tail(); rd_cnt += sizeof(_deq_tail); } else { // Tail or part of tail only outstanding, complete tail const std::size_t tail_offs = rec_offs - sizeof(deq_hdr_t) - _deq_hdr._xidsize; const std::size_t tail_rem = sizeof(rec_tail_t) - tail_offs; std::memcpy((char*)&_deq_tail + tail_offs, rptr, tail_rem); chk_tail(); rd_cnt = tail_rem; } } else if (hdr_xid_dblks - rec_offs_dblks <= max_size_dblks) { // Remainder of xid fits within this page, tail split const std::size_t xid_offs = rec_offs - sizeof(deq_hdr_t); const std::size_t xid_rem = _deq_hdr._xidsize - xid_offs; std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); rd_cnt += xid_rem; const std::size_t tail_rem = (max_size_dblks * QLS_DBLK_SIZE_BYTES) - rd_cnt; if (tail_rem) { std::memcpy((void*)&_deq_tail, ((char*)rptr + xid_rem), tail_rem); rd_cnt += tail_rem; } } else { // Remainder of xid split const std::size_t xid_cp_size = (max_size_dblks * QLS_DBLK_SIZE_BYTES); std::memcpy((char*)_buff + rec_offs - sizeof(deq_hdr_t), rptr, xid_cp_size); rd_cnt += xid_cp_size; } } else // Start of record { // Get and check header //_deq_hdr.hdr_copy(h); ::rec_hdr_copy(&_deq_hdr._rhdr, &h); rd_cnt = sizeof(rec_hdr_t); std::memcpy(&_deq_hdr._deq_rid, (char*)rptr + rd_cnt, sizeof(u_int64_t)); rd_cnt += sizeof(uint64_t); std::memcpy(&_deq_hdr._xidsize, (char*)rptr + rd_cnt, sizeof(std::size_t)); rd_cnt = sizeof(deq_hdr_t); chk_hdr(); if (_deq_hdr._xidsize) { _buff = std::malloc(_deq_hdr._xidsize); MALLOC_CHK(_buff, "_buff", "deq_rec", "decode"); const uint32_t hdr_xid_dblks = size_dblks(sizeof(deq_hdr_t) + _deq_hdr._xidsize); const uint32_t hdr_xid_tail_dblks = size_dblks(sizeof(deq_hdr_t) + _deq_hdr._xidsize + sizeof(rec_tail_t)); // Check if record (header + xid + tail) fits within this page, we can check the // tail before the expense of copying data to memory if (hdr_xid_tail_dblks <= max_size_dblks) { // Entire header, xid and tail fits within this page std::memcpy(_buff, (char*)rptr + rd_cnt, _deq_hdr._xidsize); rd_cnt += _deq_hdr._xidsize; std::memcpy((void*)&_deq_tail, (char*)rptr + rd_cnt, sizeof(_deq_tail)); rd_cnt += sizeof(_deq_tail); chk_tail(); } else if (hdr_xid_dblks <= max_size_dblks) { // Entire header and xid fit within this page, tail split std::memcpy(_buff, (char*)rptr + rd_cnt, _deq_hdr._xidsize); rd_cnt += _deq_hdr._xidsize; const std::size_t tail_rem = (max_size_dblks * QLS_DBLK_SIZE_BYTES) - rd_cnt; if (tail_rem) { std::memcpy((void*)&_deq_tail, (char*)rptr + rd_cnt, tail_rem); rd_cnt += tail_rem; } } else { // Header fits within this page, xid split const std::size_t xid_cp_size = (max_size_dblks * QLS_DBLK_SIZE_BYTES) - rd_cnt; std::memcpy(_buff, (char*)rptr + rd_cnt, xid_cp_size); rd_cnt += xid_cp_size; } } } return size_dblks(rd_cnt); }