Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Memory Segments

Memory Segments - Medieval Castle Memory Segments - Medieval Castle

Overview

Segments represent contiguous virtual address ranges with uniform properties. The seg structure provides a framework for managing different types of memory regions through pluggable segment drivers. Each segment type implements operations for fault handling, protection changes, and synchronization.

Segment Structure

struct seg {
    addr_t s_base;           /* base virtual address */
    u_int s_size;            /* size in bytes */
    struct as *s_as;         /* containing address space */
    struct seg *s_next;      /* next segment in address space */
    struct seg *s_prev;      /* previous segment */
    struct seg_ops *s_ops;   /* segment operations */
    caddr_t s_data;          /* driver private data */
};

The segment list is maintained in sorted order by base address. The s_ops pointer provides the interface to segment driver operations.

Segment Allocation

The seg_alloc() function (vm_seg.c:66) allocates and attaches a segment:

struct seg *
seg_alloc(as, base, size)
    struct as *as;
    register addr_t base;
    register u_int size;
{
    register struct seg *new;
    addr_t segbase;
    u_int segsize;

    segbase = (addr_t)((u_int)base & PAGEMASK);
    segsize =
        (((u_int)(base + size) + PAGEOFFSET) & PAGEMASK) - (u_int)segbase;

    if (!valid_va_range(&segbase, &segsize, segsize, AH_LO))
        return ((struct seg *)NULL);

    new = (struct seg *)kmem_fast_alloc((caddr_t *)&seg_freelist,
        sizeof (*seg_freelist), seg_freeincr, KM_SLEEP);
    struct_zero((caddr_t)new, sizeof (*new));
    if (seg_attach(as, segbase, segsize, new) < 0) {
        kmem_fast_free((caddr_t *)&seg_freelist, (char *)new);
        return ((struct seg *)NULL);
    }
    return (new);
}

Addresses and sizes are page-aligned using PAGEMASK. The fast allocator maintains a freelist of segment structures to avoid frequent kmem_alloc() calls.

Segment Attachment

The seg_attach() function (vm_seg.c:101) links the segment into the address space:

int
seg_attach(as, base, size, seg)
    struct as *as;
    addr_t base;
    u_int size;
    struct seg *seg;
{
    seg->s_as = as;
    seg->s_base = base;
    seg->s_size = size;
    return (as_addseg(as, seg));
}

The as_addseg() function inserts the segment into the sorted list, checking for overlaps with existing segments. Overlapping segments cause allocation failure.

Segment Operations

Each segment driver provides a seg_ops structure with function pointers:

struct seg_ops {
    int (*dup)(struct seg *, struct seg *);
    int (*unmap)(struct seg *, addr_t, u_int);
    void (*free)(struct seg *);
    faultcode_t (*fault)(struct seg *, addr_t, u_int, enum fault_type,
                         enum seg_rw);
    int (*setprot)(struct seg *, addr_t, u_int, uint);
    int (*checkprot)(struct seg *, addr_t, uint);
    int (*sync)(struct seg *, addr_t, u_int, int, uint);
};

The fault operation handles page faults within the segment. The dup operation creates copy-on-write mappings for fork. The unmap operation removes mappings and frees resources.

Common Segment Types

seg_vn: File-backed segments for executables and mmap’d files seg_u: Stack and heap segments with anonymous backing seg_dev: Device memory mappings seg_kmem: Kernel memory segments seg_map: Kernel temporary mappings

Each type provides specialized handling for its particular use case while conforming to the common segment driver interface.

Segment Operations Figure 2.4.1: Segment Operations Vector