const char *test_mapping1(void) { int rc; size_t buffer1_len = BUFFER1_PAGES * PAGE_SIZE; size_t buffer2_len = BUFFER2_PAGES * PAGE_SIZE; void *buffer1 = create_as_area(buffer1_len); void *buffer2 = create_as_area(buffer2_len); if (!buffer1 || !buffer2) { return "Cannot allocate memory"; } touch_area(buffer1, buffer1_len); touch_area(buffer2, buffer2_len); /* Now verify that mapping to physical frames exist. */ if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, EOK)) { return "Failed to find mapping (buffer1)"; } if (!VERIFY_MAPPING(buffer2, BUFFER2_PAGES, EOK)) { return "Failed to find mapping (buffer2)"; } /* Let's destroy the buffer1 area and access it again. */ rc = as_area_destroy(buffer1); if (rc != EOK) { return "Failed to destroy AS area"; } if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, ENOENT)) { return "Mapping of destroyed area still exists"; } /* clean-up */ rc = as_area_destroy(buffer2); if (rc != EOK) { return "Failed to destroy AS area"; } return NULL; }
/** Create a program using an existing address space. * * @param as Address space containing a binary program image. * @param entry_addr Program entry-point address in program address space. * @param name Name to set for the program's task. * @param prg Buffer for storing program information. * * @return EOK on success or negative error code. * */ int program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *prg) { prg->loader_status = EE_OK; prg->task = task_create(as, name); if (!prg->task) return ELIMIT; /* * Create the stack address space area. */ uintptr_t virt = USTACK_ADDRESS; as_area_t *area = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, STACK_SIZE, AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, 0); if (!area) { task_destroy(prg->task); return ENOMEM; } uspace_arg_t *kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); kernel_uarg->uspace_entry = (void *) entry_addr; kernel_uarg->uspace_stack = (void *) virt; kernel_uarg->uspace_stack_size = STACK_SIZE; kernel_uarg->uspace_thread_function = NULL; kernel_uarg->uspace_thread_arg = NULL; kernel_uarg->uspace_uarg = NULL; /* * Create the main thread. */ prg->main_thread = thread_create(uinit, kernel_uarg, prg->task, THREAD_FLAG_USPACE, "uinit"); if (!prg->main_thread) { free(kernel_uarg); as_area_destroy(as, virt); task_destroy(prg->task); return ELIMIT; } return EOK; }
/** Get time of day * * The time variables are memory mapped (read-only) from kernel which * updates them periodically. * * As it is impossible to read 2 values atomically, we use a trick: * First we read the seconds, then we read the microseconds, then we * read the seconds again. If a second elapsed in the meantime, set * the microseconds to zero. * * This assures that the values returned by two subsequent calls * to gettimeofday() are monotonous. * */ int gettimeofday(struct timeval *tv, struct timezone *tz) { if (ktime == NULL) { uintptr_t faddr; int rc = sysinfo_get_value("clock.faddr", &faddr); if (rc != EOK) { errno = rc; return -1; } void *addr; rc = physmem_map((void *) faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE, &addr); if (rc != EOK) { as_area_destroy(addr); errno = rc; return -1; } ktime = addr; } if (tz) { tz->tz_minuteswest = 0; tz->tz_dsttime = DST_NONE; } sysarg_t s2 = ktime->seconds2; read_barrier(); tv->tv_usec = ktime->useconds; read_barrier(); sysarg_t s1 = ktime->seconds1; if (s1 != s2) { tv->tv_sec = max(s1, s2); tv->tv_usec = 0; } else tv->tv_sec = s1; return 0; }
/** Try to shrink heap * * Should be called only inside the critical section. * In all cases the next pointer is reset. * * @param area Last modified heap area. * */ static void heap_shrink(heap_area_t *area) { area_check(area); heap_block_foot_t *last_foot = (heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area); heap_block_head_t *last_head = BLOCK_HEAD(last_foot); block_check((void *) last_head); malloc_assert(last_head->area == area); if (last_head->free) { /* * The last block of the heap area is * unused. The area might be potentially * shrunk. */ heap_block_head_t *first_head = (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(area); block_check((void *) first_head); malloc_assert(first_head->area == area); size_t shrink_size = ALIGN_DOWN(last_head->size, PAGE_SIZE); if (first_head == last_head) { /* * The entire heap area consists of a single * free heap block. This means we can get rid * of it entirely. */ heap_area_t *prev = area->prev; heap_area_t *next = area->next; if (prev != NULL) { area_check(prev); prev->next = next; } else first_heap_area = next; if (next != NULL) { area_check(next); next->prev = prev; } else last_heap_area = prev; as_area_destroy(area->start); } else if (shrink_size >= SHRINK_GRANULARITY) { /* * Make sure that we always shrink the area * by a multiple of page size and update * the block layout accordingly. */ size_t asize = (size_t) (area->end - area->start) - shrink_size; void *end = (void *) ((uintptr_t) area->start + asize); /* Resize the address space area */ int ret = as_area_resize(area->start, asize, 0); if (ret != EOK) abort(); /* Update heap area parameters */ area->end = end; size_t excess = ((size_t) area->end) - ((size_t) last_head); if (excess > 0) { if (excess >= STRUCT_OVERHEAD) { /* * The previous block cannot be free and there * is enough free space left in the area to * create a new free block. */ block_init((void *) last_head, excess, true, area); } else { /* * The excess is small. Therefore just enlarge * the previous block. */ heap_block_foot_t *prev_foot = (heap_block_foot_t *) (((uintptr_t) last_head) - sizeof(heap_block_foot_t)); heap_block_head_t *prev_head = BLOCK_HEAD(prev_foot); block_check((void *) prev_head); block_init(prev_head, prev_head->size + excess, prev_head->free, area); } } } } next_fit = NULL; }
int ega_init(void) { sysarg_t present; int rc = sysinfo_get_value("fb", &present); if (rc != EOK) present = false; if (!present) return ENOENT; sysarg_t kind; rc = sysinfo_get_value("fb.kind", &kind); if (rc != EOK) kind = (sysarg_t) -1; if (kind != 2) return EINVAL; sysarg_t paddr; rc = sysinfo_get_value("fb.address.physical", &paddr); if (rc != EOK) return rc; rc = sysinfo_get_value("fb.width", &ega.cols); if (rc != EOK) return rc; rc = sysinfo_get_value("fb.height", &ega.rows); if (rc != EOK) return rc; rc = pio_enable((void*)EGA_IO_BASE, EGA_IO_SIZE, NULL); if (rc != EOK) return rc; ega.size = (ega.cols * ega.rows) << 1; rc = physmem_map((void *) paddr, ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr); if (rc != EOK) return rc; sysarg_t blinking; rc = sysinfo_get_value("fb.blinking", &blinking); if (rc != EOK) blinking = false; ega.style_normal = 0xf0; ega.style_inverted = 0x0f; if (blinking) { ega.style_normal &= 0x77; ega.style_inverted &= 0x77; } outdev_t *dev = outdev_register(&ega_ops, (void *) &ega); if (dev == NULL) { as_area_destroy(ega.addr); return EINVAL; } return EOK; }
int munmap(void *start, size_t length) { return as_area_destroy(start); }
/** * Record directly from a device to a file. * @param device The device. * @param file The file. * @return Error code. */ int drecord(const char *device, const char *file) { int ret = EOK; audio_pcm_sess_t *session = NULL; if (str_cmp(device, "default") == 0) { session = audio_pcm_open_default(); } else { session = audio_pcm_open(device); } if (!session) { printf("Failed to connect to device %s.\n", device); return 1; } printf("Recording on device: %s.\n", device); if (audio_pcm_query_cap(session, AUDIO_CAP_CAPTURE) <= 0) { printf("Device %s does not support recording\n", device); ret = ENOTSUP; goto close_session; } const char* info = NULL; ret = audio_pcm_get_info_str(session, &info); if (ret != EOK) { printf("Failed to get PCM info.\n"); goto close_session; } printf("Capturing on %s.\n", info); free(info); record_t rec; record_initialize(&rec, session); ret = audio_pcm_get_buffer(rec.device, &rec.buffer.base, &rec.buffer.size); if (ret != EOK) { printf("Failed to get PCM buffer: %s.\n", str_error(ret)); goto close_session; } printf("Buffer: %p %zu.\n", rec.buffer.base, rec.buffer.size); rec.file = fopen(file, "w"); if (rec.file == NULL) { ret = ENOENT; printf("Failed to open file: %s.\n", file); goto cleanup; } wave_header_t header; fseek(rec.file, sizeof(header), SEEK_SET); if (ret != EOK) { printf("Error parsing wav header\n"); goto cleanup; } if (audio_pcm_query_cap(rec.device, AUDIO_CAP_INTERRUPT) > 0) record_fragment(&rec, format); else printf("Recording method is not supported"); //TODO consider buffer position interface wav_init_header(&header, format, ftell(rec.file) - sizeof(header)); fseek(rec.file, 0, SEEK_SET); fwrite(&header, sizeof(header), 1, rec.file); cleanup: fclose(rec.file); as_area_destroy(rec.buffer.base); audio_pcm_release_buffer(rec.device); close_session: audio_pcm_close(session); return ret == EOK ? 0 : 1; }