My Project
Loading...
Searching...
No Matches
vspace::internals Namespace Reference

Data Structures

class  FastLock
struct  ProcessInfo
struct  MetaPage
struct  ProcessChannel
struct  Block
struct  VSeg
struct  VMem
struct  refcount_t
class  Mutex

Typedefs

typedef size_t segaddr_t
typedef size_t vaddr_t
typedef int ipc_signal_t

Enumerations

enum  SignalState { Waiting = 0 , Pending = 1 , Accepted = 2 }

Functions

static void lock_allocator ()
static void unlock_allocator ()
static void print_freelists ()
void vmem_free (vaddr_t vaddr)
vaddr_t vmem_alloc (size_t size)
void init_flock_struct (struct flock &lock_info, size_t offset, size_t len, bool lock)
void lock_file (int fd, size_t offset, size_t len)
void unlock_file (int fd, size_t offset, size_t len)
void lock_metapage ()
void unlock_metapage ()
void init_metapage (bool create)
static void lock_process (int processno)
static void unlock_process (int processno)
static ProcessInfoprocess_info (int processno)
bool send_signal (int processno, ipc_signal_t sig, bool lock)
ipc_signal_t check_signal (bool resume, bool lock)
void accept_signals ()
ipc_signal_t wait_signal (bool lock)
void drop_pending_signals ()
Blockblock_ptr (vaddr_t vaddr)
static int find_level (size_t size)
static segaddr_t find_buddy (segaddr_t addr, int level)
static vaddr_t allocated_ptr_to_vaddr (void *ptr)

Variables

size_t config [4] = { METABLOCK_SIZE, MAX_PROCESS, SEGMENT_SIZE, MAX_SEGMENTS }
const segaddr_t SEGADDR_NULL = ~(segaddr_t) 0
const vaddr_t VADDR_NULL = ~(segaddr_t) 0
static const int MAX_PROCESS = 64
static const size_t METABLOCK_SIZE = 128 * 1024
static const int LOG2_SEGMENT_SIZE = 28
static const int LOG2_MAX_SEGMENTS = 10
static const size_t MAX_SEGMENTS = 1 << LOG2_MAX_SEGMENTS
static const size_t SEGMENT_SIZE = 1 << LOG2_SEGMENT_SIZE
static const size_t SEGMENT_MASK = (SEGMENT_SIZE - 1)
static VMemvmem = VMem::vmem_global

Data Structure Documentation

◆ vspace::internals::ProcessInfo

struct vspace::internals::ProcessInfo

Definition at line 1499 of file vspace.h.

Data Fields
pid_t pid
ipc_signal_t signal
SignalState sigstate

◆ vspace::internals::MetaPage

struct vspace::internals::MetaPage

Definition at line 1508 of file vspace.h.

Data Fields
FastLock allocator_lock
size_t config_header[4]
vaddr_t freelist[LOG2_SEGMENT_SIZE+1]
ProcessInfo process_info[MAX_PROCESS]
int segment_count

◆ vspace::internals::ProcessChannel

struct vspace::internals::ProcessChannel

Definition at line 1525 of file vspace.h.

Data Fields
int fd_read
int fd_write

Typedef Documentation

◆ ipc_signal_t

Definition at line 1481 of file vspace.h.

◆ segaddr_t

Definition at line 1412 of file vspace.h.

◆ vaddr_t

Definition at line 1414 of file vspace.h.

Enumeration Type Documentation

◆ SignalState

Enumerator
Waiting 
Pending 
Accepted 

Definition at line 1493 of file vspace.h.

1493 {
1494 Waiting = 0,
1495 Pending = 1,
1496 Accepted = 2,
1497};

Function Documentation

◆ accept_signals()

void vspace::internals::accept_signals ( )

Definition at line 1096 of file vspace.cc.

1096 {
1097 lock_process(vmem.current_process);
1098 process_info(vmem.current_process).sigstate = Waiting;
1099 unlock_process(vmem.current_process);
1100}
static ProcessInfo & process_info(int processno)
Definition vspace.cc:990
static void unlock_process(int processno)
Definition vspace.cc:984
static void lock_process(int processno)
Definition vspace.cc:978
static VMem & vmem
Definition vspace.h:1635

◆ allocated_ptr_to_vaddr()

vaddr_t vspace::internals::allocated_ptr_to_vaddr ( void * ptr)
inlinestatic

Definition at line 1697 of file vspace.h.

1697 {
1698 char *addr = (char *) ptr - sizeof(Block);
1699 vaddr_t info = ((Block *) addr)->prev;
1700 int seg = info & (MAX_SEGMENTS - 1);
1701 unsigned char *segstart = vmem.segments[seg].base;
1702 size_t offset = (unsigned char *) ptr - segstart;
1703 return (seg << LOG2_SEGMENT_SIZE) | offset;
1704}
STATIC_VAR int offset
Definition janet.cc:29
#define info
Definition libparse.cc:1256
static const size_t MAX_SEGMENTS
Definition vspace.h:1423
static const int LOG2_SEGMENT_SIZE
Definition vspace.h:1421

◆ block_ptr()

Block * vspace::internals::block_ptr ( vaddr_t vaddr)
inline

Definition at line 1637 of file vspace.h.

1637 {
1638 return vmem.block_ptr(vaddr);
1639}

◆ check_signal()

ipc_signal_t vspace::internals::check_signal ( bool resume,
bool lock )

Definition at line 1017 of file vspace.cc.

1017 {
1019 if (lock)
1020 lock_process(vmem.current_process);
1021 SignalState sigstate = process_info(vmem.current_process).sigstate;
1022 switch (sigstate) {
1023 case Waiting:
1024 case Pending: {
1025 int fd = vmem.channels[vmem.current_process].fd_read;
1026 char buf[1];
1027 if (lock && sigstate == Waiting) {
1028 unlock_process(vmem.current_process);
1029 loop
1030 {
1031 #if defined(HAVE_POLL) && !defined(__APPLE__)
1032 // fd is restricted on OsX by ulimit "file descriptors" (256)
1033 pollfd pfd;
1034 pfd.fd = fd;
1035 pfd.events = POLLIN;
1036 int rv = poll(&pfd, 1, 500000); /* msec*/
1037 #else
1038 // fd is restricted to <=1024
1039 fd_set set;
1040 FD_ZERO(&set); /* clear the set */
1041 FD_SET(fd, &set); /* add our file descriptor to the set */
1042 struct timeval timeout;
1043 timeout.tv_sec = 500;
1044 timeout.tv_usec = 0;
1045 int rv = si_select(fd + 1, &set, NULL, NULL, &timeout);
1046 #endif
1047 if (rv== -1) continue; /* an error occurred */
1048 if (rv== 0) break; /* timeout */
1049 while(read(fd, buf, 1)!=1) {}
1050 break;
1051 }
1053 } else {
1054 loop
1055 {
1056 #if defined(HAVE_POLL) && !defined(__APPLE__)
1057 // fd is restricted on OsX by ulimit "file descriptors" (256)
1058 pollfd pfd;
1059 pfd.fd = fd;
1060 pfd.events = POLLIN;
1061 int rv = poll(&pfd, 1, 500000); /* msec*/
1062 #else
1063 // fd is restricted to <=1024
1064 fd_set set;
1065 FD_ZERO(&set); /* clear the set */
1066 FD_SET(fd, &set); /* add our file descriptor to the set */
1067 struct timeval timeout;
1068 timeout.tv_sec = 500;
1069 timeout.tv_usec = 0;
1070 int rv = si_select(fd + 1, &set, NULL, NULL, &timeout);
1071 #endif
1072 if (rv== -1) continue; /* an error occurred */
1073 if (rv== 0) break;/* timeout */
1074 while(read(fd, buf, 1)!=1) {}
1075 break;
1076 }
1077 }
1078 result = process_info(vmem.current_process).signal;
1079 process_info(vmem.current_process).sigstate
1080 = resume ? Waiting : Accepted;
1081 if (lock)
1082 unlock_process(vmem.current_process);
1083 break;
1084 }
1085 case Accepted:
1086 result = process_info(vmem.current_process).signal;
1087 if (resume)
1088 process_info(vmem.current_process).sigstate = Waiting;
1089 if (lock)
1090 unlock_process(vmem.current_process);
1091 break;
1092 }
1093 return result;
1094}
return result
#define NULL
Definition omList.c:12
int status read
Definition si_signals.h:69
int status int fd
Definition si_signals.h:69
int status int void * buf
Definition si_signals.h:69
#define loop
Definition structs.h:71

◆ drop_pending_signals()

void vspace::internals::drop_pending_signals ( )

◆ find_buddy()

segaddr_t vspace::internals::find_buddy ( segaddr_t addr,
int level )
inlinestatic

Definition at line 1690 of file vspace.h.

1690 {
1691 return addr ^ (1 << level);
1692}
int level(const CanonicalForm &f)

◆ find_level()

int vspace::internals::find_level ( size_t size)
inlinestatic

Definition at line 1681 of file vspace.h.

1681 {
1682 int level = 0;
1683 while ((1 << (level + 8)) <= size)
1684 level += 8;
1685 while ((1 << level) < size)
1686 level++;
1687 return level;
1688}
int size(const CanonicalForm &f, const Variable &v)
int size ( const CanonicalForm & f, const Variable & v )
Definition cf_ops.cc:600

◆ init_flock_struct()

void vspace::internals::init_flock_struct ( struct flock & lock_info,
size_t offset,
size_t len,
bool lock )

Definition at line 925 of file vspace.cc.

926 {
927 lock_info.l_start = offset;
928 lock_info.l_len = len;
929 lock_info.l_pid = 0;
930 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
931 lock_info.l_whence = SEEK_SET;
932}
#define SEEK_SET
Definition mod2.h:115

◆ init_metapage()

void vspace::internals::init_metapage ( bool create)

Definition at line 954 of file vspace.cc.

954 {
955 if (create) {
956 if (ftruncate(vmem.fd, METABLOCK_SIZE) != 0) {
957 char err_msg[256];
958 snprintf(err_msg, sizeof(err_msg), "out of memory in vspace:init_metapage: %s", strerror(errno));
959 WerrorS(err_msg);
960 return;
961 }
962 }
963 vmem.metapage = (MetaPage *) mmap(
964 NULL, METABLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, vmem.fd, 0);
965 if (create) {
966 std::memcpy(vmem.metapage->config_header, config, sizeof(config));
967 for (int i = 0; i <= LOG2_SEGMENT_SIZE; i++) {
969 }
970 vmem.metapage->segment_count = 0;
971 vmem.metapage->allocator_lock = FastLock(metapageaddr(allocator_lock));
972 } else {
973 assert(std::memcmp(vmem.metapage->config_header, config,
974 sizeof(config)) != 0);
975 }
976}
int i
Definition cfEzgcd.cc:132
void WerrorS(const char *s)
Definition feFopen.cc:24
NodeM * create()
Definition janet.cc:757
const vaddr_t VADDR_NULL
Definition vspace.h:1417
vaddr_t freelist[LOG2_SEGMENT_SIZE+1]
Definition vspace.h:1511
static const size_t METABLOCK_SIZE
Definition vspace.h:1420
size_t config[4]
Definition vspace.cc:634
internals::Mutex FastLock
Definition vspace.h:2340
#define assert(A)
Definition svd_si.h:3
#define metapageaddr(field)
Definition vspace.cc:641

◆ lock_allocator()

void vspace::internals::lock_allocator ( )
static

Definition at line 787 of file vspace.cc.

787 {
788 vmem.metapage->allocator_lock.lock();
789}

◆ lock_file()

void vspace::internals::lock_file ( int fd,
size_t offset,
size_t len )

Definition at line 934 of file vspace.cc.

934 {
935 struct flock lock_info;
936 init_flock_struct(lock_info, offset, len, true);
937 fcntl(fd, F_SETLKW, &lock_info);
938}
void init_flock_struct(struct flock &lock_info, size_t offset, size_t len, bool lock)
Definition vspace.cc:925

◆ lock_metapage()

void vspace::internals::lock_metapage ( )

Definition at line 946 of file vspace.cc.

946 {
947 lock_file(vmem.fd, 0);
948}
void lock_file(int fd, size_t offset, size_t len)
Definition vspace.cc:934

◆ lock_process()

void vspace::internals::lock_process ( int processno)
static

Definition at line 978 of file vspace.cc.

978 {
979 lock_file(vmem.fd,
981 + sizeof(ProcessInfo) * vmem.current_process);
982}

◆ print_freelists()

void vspace::internals::print_freelists ( )
static

Definition at line 795 of file vspace.cc.

795 {
796 for (int i = 0; i <= LOG2_SEGMENT_SIZE; i++) {
797 vaddr_t vaddr = vmem.freelist[i];
798 if (vaddr != VADDR_NULL) {
799 std::printf("%2d: %ld", i, (long)vaddr);
800 vaddr_t prev = block_ptr(vaddr)->prev;
801 if (prev != VADDR_NULL) {
802 std::printf("(%ld)", (long)prev);
803 }
804 assert(block_ptr(vaddr)->prev == VADDR_NULL);
805 for (;;) {
806 vaddr_t last_vaddr = vaddr;
807 Block *block = block_ptr(vaddr);
808 vaddr = block->next;
809 if (vaddr == VADDR_NULL)
810 break;
811 std::printf(" -> %ld", (long)vaddr);
812 vaddr_t prev = block_ptr(vaddr)->prev;
813 if (prev != last_vaddr) {
814 std::printf("(%ld)", (long)prev);
815 }
816 }
817 std::printf("\n");
818 }
819 }
820 std::fflush(stdout);
821}
Block * block_ptr(vaddr_t vaddr)
Definition vspace.h:1637
#define block
Definition scanner.cc:646

◆ process_info()

ProcessInfo & vspace::internals::process_info ( int processno)
static

Definition at line 990 of file vspace.cc.

990 {
991 return vmem.metapage->process_info[processno];
992}

◆ send_signal()

bool vspace::internals::send_signal ( int processno,
ipc_signal_t sig,
bool lock )

Definition at line 994 of file vspace.cc.

994 {
995 if (lock)
996 lock_process(processno);
997 if (process_info(processno).sigstate != Waiting) {
998 unlock_process(processno);
999 return false;
1000 }
1001 if (processno == vmem.current_process) {
1002 process_info(processno).sigstate = Accepted;
1003 process_info(processno).signal = sig;
1004 } else {
1005 process_info(processno).sigstate = Pending;
1006 process_info(processno).signal = sig;
1007 int fd = vmem.channels[processno].fd_write;
1008 char buf[1] = { 0 };
1009 while (write(fd, buf, 1) != 1) {
1010 }
1011 }
1012 if (lock)
1013 unlock_process(processno);
1014 return true;
1015}
ProcessChannel channels[MAX_PROCESS]
Definition vspace.h:1595

◆ unlock_allocator()

void vspace::internals::unlock_allocator ( )
static

Definition at line 791 of file vspace.cc.

791 {
792 vmem.metapage->allocator_lock.unlock();
793}

◆ unlock_file()

void vspace::internals::unlock_file ( int fd,
size_t offset,
size_t len )

Definition at line 940 of file vspace.cc.

940 {
941 struct flock lock_info;
942 init_flock_struct(lock_info, offset, len, false);
943 fcntl(fd, F_SETLKW, &lock_info);
944}

◆ unlock_metapage()

void vspace::internals::unlock_metapage ( )

Definition at line 950 of file vspace.cc.

950 {
951 unlock_file(vmem.fd, 0);
952}
void unlock_file(int fd, size_t offset, size_t len)
Definition vspace.cc:940

◆ unlock_process()

void vspace::internals::unlock_process ( int processno)
static

Definition at line 984 of file vspace.cc.

984 {
985 unlock_file(vmem.fd,
987 + sizeof(ProcessInfo) * vmem.current_process);
988}

◆ vmem_alloc()

vaddr_t vspace::internals::vmem_alloc ( size_t size)

Definition at line 875 of file vspace.cc.

875 {
877 #if defined(__GNUC__) && (__GNUC__>11)
878 size_t alloc_size = size + (sizeof(vaddr_t)*2);
879 #else
880 size_t alloc_size = size + offsetof(Block, data);
881 #endif
882 int level = find_level(alloc_size);
883 int flevel = level;
884 while (flevel < LOG2_SEGMENT_SIZE && vmem.freelist[flevel] == VADDR_NULL)
885 flevel++;
886 if (vmem.freelist[flevel] == VADDR_NULL) {
887 vmem.add_segment();
888 }
890 while (flevel > level) {
891 // get and split a block
892 vaddr_t blockaddr = vmem.freelist[flevel];
893 assert((blockaddr & ((1 << flevel) - 1)) == 0);
894 Block *block = vmem.block_ptr(blockaddr);
895 vmem.freelist[flevel] = block->next;
896 if (vmem.freelist[flevel] != VADDR_NULL)
898 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
899 Block *block2 = vmem.block_ptr(blockaddr2);
900 flevel--;
901 block2->next = vmem.freelist[flevel];
902 block2->prev = blockaddr;
903 block->next = blockaddr2;
904 block->prev = VADDR_NULL;
905 // block->prev == VADDR_NULL already.
906 vmem.freelist[flevel] = blockaddr;
907 }
910 vaddr_t vaddr = vmem.freelist[level];
911 #if defined(__GNUC__) && (__GNUC__>11)
912 vaddr_t result = vaddr + (sizeof(vaddr_t)*2);
913 #else
914 vaddr_t result = vaddr + offsetof(Block, data);
915 #endif
916 vmem.freelist[level] = block->next;
917 if (block->next != VADDR_NULL)
919 block->mark_as_allocated(vaddr, level);
921 memset(block->data, 0, size);
922 return result;
923}
static void lock_allocator()
Definition vspace.cc:787
static int find_level(size_t size)
Definition vspace.h:1681
static void unlock_allocator()
Definition vspace.cc:791
void ensure_is_mapped(vaddr_t vaddr)
Definition vspace.h:1615
Block * block_ptr(vaddr_t vaddr)
Definition vspace.h:1610

◆ vmem_free()

void vspace::internals::vmem_free ( vaddr_t vaddr)

Definition at line 823 of file vspace.cc.

823 {
825 #if defined(__GNUC__) && (__GNUC__>11)
826 vaddr -= (sizeof(vaddr_t)*2);
827 #else
828 vaddr -= offsetof(Block, data);
829 #endif
830 vmem.ensure_is_mapped(vaddr);
831 size_t segno = vmem.segment_no(vaddr);
832 VSeg seg = vmem.segment(vaddr);
833 segaddr_t addr = vmem.segaddr(vaddr);
834 int level = seg.block_ptr(addr)->level();
835 assert(!seg.is_free(addr));
836 while (level < LOG2_SEGMENT_SIZE) {
837 segaddr_t buddy = find_buddy(addr, level);
838 Block *block = seg.block_ptr(buddy);
839 // is buddy free and at the same level?
840 if (!block->is_free() || block->level() != level)
841 break;
842 // remove buddy from freelist.
843 Block *prev = vmem.block_ptr(block->prev);
844 Block *next = vmem.block_ptr(block->next);
845 block->data[0] = level;
846 if (prev) {
847 assert(prev->next == vmem.vaddr(segno, buddy));
848 prev->next = block->next;
849 } else {
850 // head of freelist.
851 assert(vmem.freelist[level] == vmem.vaddr(segno, buddy));
852 vmem.freelist[level] = block->next;
853 }
854 if (next) {
855 assert(next->prev == vmem.vaddr(segno, buddy));
856 next->prev = block->prev;
857 }
858 // coalesce block with buddy
859 level++;
860 if (buddy < addr)
861 addr = buddy;
862 }
863 // Add coalesced block to free list
864 Block *block = seg.block_ptr(addr);
866 block->next = vmem.freelist[level];
867 block->mark_as_free(level);
868 vaddr_t blockaddr = vmem.vaddr(segno, addr);
869 if (block->next != VADDR_NULL)
870 vmem.block_ptr(block->next)->prev = blockaddr;
871 vmem.freelist[level] = blockaddr;
873}
ListNode * next
Definition janet.h:31
static segaddr_t find_buddy(segaddr_t addr, int level)
Definition vspace.h:1690
vaddr_t vaddr(size_t segno, segaddr_t addr)
Definition vspace.h:1602
Block * block_ptr(segaddr_t addr)
Definition vspace.h:1571

◆ wait_signal()

ipc_signal_t vspace::internals::wait_signal ( bool lock)

Definition at line 1102 of file vspace.cc.

1102 {
1103 return check_signal(true, lock);
1104}
ipc_signal_t check_signal(bool resume, bool lock)
Definition vspace.cc:1017

Variable Documentation

◆ config

size_t vspace::internals::config = { METABLOCK_SIZE, MAX_PROCESS, SEGMENT_SIZE, MAX_SEGMENTS }

Definition at line 633 of file vspace.cc.

static const size_t SEGMENT_SIZE
Definition vspace.h:1424
static const int MAX_PROCESS
Definition vspace.h:1419

◆ LOG2_MAX_SEGMENTS

const int vspace::internals::LOG2_MAX_SEGMENTS = 10
static

Definition at line 1422 of file vspace.h.

◆ LOG2_SEGMENT_SIZE

const int vspace::internals::LOG2_SEGMENT_SIZE = 28
static

Definition at line 1421 of file vspace.h.

◆ MAX_PROCESS

const int vspace::internals::MAX_PROCESS = 64
static

Definition at line 1419 of file vspace.h.

◆ MAX_SEGMENTS

const size_t vspace::internals::MAX_SEGMENTS = 1 << LOG2_MAX_SEGMENTS
static

Definition at line 1423 of file vspace.h.

◆ METABLOCK_SIZE

const size_t vspace::internals::METABLOCK_SIZE = 128 * 1024
static

Definition at line 1420 of file vspace.h.

◆ SEGADDR_NULL

const segaddr_t vspace::internals::SEGADDR_NULL = ~(segaddr_t) 0

Definition at line 1416 of file vspace.h.

◆ SEGMENT_MASK

const size_t vspace::internals::SEGMENT_MASK = (SEGMENT_SIZE - 1)
static

Definition at line 1425 of file vspace.h.

◆ SEGMENT_SIZE

const size_t vspace::internals::SEGMENT_SIZE = 1 << LOG2_SEGMENT_SIZE
static

Definition at line 1424 of file vspace.h.

◆ VADDR_NULL

const vaddr_t vspace::internals::VADDR_NULL = ~(segaddr_t) 0

Definition at line 1417 of file vspace.h.

◆ vmem

VMem& vspace::internals::vmem = VMem::vmem_global
static

Definition at line 1635 of file vspace.h.