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

Data Structures

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

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::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

◆ 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

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 1069 of file vspace.cc.

1069 {
1070 lock_process(vmem.current_process);
1071 process_info(vmem.current_process).sigstate = Waiting;
1072 unlock_process(vmem.current_process);
1073}
static ProcessInfo & process_info(int processno)
Definition vspace.cc:963
static void unlock_process(int processno)
Definition vspace.cc:957
static void lock_process(int processno)
Definition vspace.cc:951
static VMem & vmem
Definition vspace.h:1635

◆ allocated_ptr_to_vaddr()

static 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 990 of file vspace.cc.

990 {
992 if (lock)
993 lock_process(vmem.current_process);
994 SignalState sigstate = process_info(vmem.current_process).sigstate;
995 switch (sigstate) {
996 case Waiting:
997 case Pending: {
998 int fd = vmem.channels[vmem.current_process].fd_read;
999 char buf[1];
1000 if (lock && sigstate == Waiting) {
1001 unlock_process(vmem.current_process);
1002 loop
1003 {
1004 #if defined(HAVE_POLL) && !defined(__APPLE__)
1005 // fd is restricted on OsX by ulimit "file descriptors" (256)
1006 pollfd pfd;
1007 pfd.fd = fd;
1008 pfd.events = POLLIN;
1009 int rv = poll(&pfd, 1, 500000); /* msec*/
1010 #else
1011 // fd is restricted to <=1024
1012 fd_set set;
1013 FD_ZERO(&set); /* clear the set */
1014 FD_SET(fd, &set); /* add our file descriptor to the set */
1015 struct timeval timeout;
1016 timeout.tv_sec = 500;
1017 timeout.tv_usec = 0;
1018 int rv = si_select(fd + 1, &set, NULL, NULL, &timeout);
1019 #endif
1020 if (rv== -1) continue; /* an error occurred */
1021 if (rv== 0) break; /* timeout */
1022 while(read(fd, buf, 1)!=1) {}
1023 break;
1024 }
1026 } else {
1027 loop
1028 {
1029 #if defined(HAVE_POLL) && !defined(__APPLE__)
1030 // fd is restricted on OsX by ulimit "file descriptors" (256)
1031 pollfd pfd;
1032 pfd.fd = fd;
1033 pfd.events = POLLIN;
1034 int rv = poll(&pfd, 1, 500000); /* msec*/
1035 #else
1036 // fd is restricted to <=1024
1037 fd_set set;
1038 FD_ZERO(&set); /* clear the set */
1039 FD_SET(fd, &set); /* add our file descriptor to the set */
1040 struct timeval timeout;
1041 timeout.tv_sec = 500;
1042 timeout.tv_usec = 0;
1043 int rv = si_select(fd + 1, &set, NULL, NULL, &timeout);
1044 #endif
1045 if (rv== -1) continue; /* an error occurred */
1046 if (rv== 0) break;/* timeout */
1047 while(read(fd, buf, 1)!=1) {}
1048 break;
1049 }
1050 }
1051 result = process_info(vmem.current_process).signal;
1052 process_info(vmem.current_process).sigstate
1053 = resume ? Waiting : Accepted;
1054 if (lock)
1055 unlock_process(vmem.current_process);
1056 break;
1057 }
1058 case Accepted:
1059 result = process_info(vmem.current_process).signal;
1060 if (resume)
1061 process_info(vmem.current_process).sigstate = Waiting;
1062 if (lock)
1063 unlock_process(vmem.current_process);
1064 break;
1065 }
1066 return result;
1067}
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()

static 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()

static 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 904 of file vspace.cc.

905 {
906 lock_info.l_start = offset;
907 lock_info.l_len = len;
908 lock_info.l_pid = 0;
909 lock_info.l_type = lock ? F_WRLCK : F_UNLCK;
910 lock_info.l_whence = SEEK_SET;
911}
#define SEEK_SET
Definition mod2.h:115

◆ init_metapage()

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

Definition at line 933 of file vspace.cc.

933 {
934 if (create)
935 ftruncate(vmem.fd, METABLOCK_SIZE);
936 vmem.metapage = (MetaPage *) mmap(
937 NULL, METABLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, vmem.fd, 0);
938 if (create) {
939 std::memcpy(vmem.metapage->config_header, config, sizeof(config));
940 for (int i = 0; i <= LOG2_SEGMENT_SIZE; i++) {
941 vmem.metapage->freelist[i] = VADDR_NULL;
942 }
945 } else {
947 sizeof(config)) != 0);
948 }
949}
int i
Definition cfEzgcd.cc:132
NodeM * create()
Definition janet.cc:757
const vaddr_t VADDR_NULL
Definition vspace.h:1417
static const size_t METABLOCK_SIZE
Definition vspace.h:1420
size_t config[4]
Definition vspace.cc:619
internals::Mutex FastLock
Definition vspace.h:2340
#define assert(A)
Definition svd_si.h:3
#define metapageaddr(field)
Definition vspace.cc:626

◆ lock_allocator()

static void vspace::internals::lock_allocator ( )
static

Definition at line 766 of file vspace.cc.

766 {
767 vmem.metapage->allocator_lock.lock();
768}

◆ lock_file()

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

Definition at line 913 of file vspace.cc.

913 {
914 struct flock lock_info;
915 init_flock_struct(lock_info, offset, len, true);
916 fcntl(fd, F_SETLKW, &lock_info);
917}
void init_flock_struct(struct flock &lock_info, size_t offset, size_t len, bool lock)
Definition vspace.cc:904

◆ lock_metapage()

void vspace::internals::lock_metapage ( )

Definition at line 925 of file vspace.cc.

925 {
926 lock_file(vmem.fd, 0);
927}
void lock_file(int fd, size_t offset, size_t len)
Definition vspace.cc:913

◆ lock_process()

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

Definition at line 951 of file vspace.cc.

951 {
952 lock_file(vmem.fd,
954 + sizeof(ProcessInfo) * vmem.current_process);
955}

◆ print_freelists()

static void vspace::internals::print_freelists ( )
static

Definition at line 774 of file vspace.cc.

774 {
775 for (int i = 0; i <= LOG2_SEGMENT_SIZE; i++) {
776 vaddr_t vaddr = vmem.freelist[i];
777 if (vaddr != VADDR_NULL) {
778 std::printf("%2d: %ld", i, (long)vaddr);
779 vaddr_t prev = block_ptr(vaddr)->prev;
780 if (prev != VADDR_NULL) {
781 std::printf("(%ld)", (long)prev);
782 }
783 assert(block_ptr(vaddr)->prev == VADDR_NULL);
784 for (;;) {
785 vaddr_t last_vaddr = vaddr;
786 Block *block = block_ptr(vaddr);
787 vaddr = block->next;
788 if (vaddr == VADDR_NULL)
789 break;
790 std::printf(" -> %ld", (long)vaddr);
791 vaddr_t prev = block_ptr(vaddr)->prev;
792 if (prev != last_vaddr) {
793 std::printf("(%ld)", (long)prev);
794 }
795 }
796 std::printf("\n");
797 }
798 }
799 std::fflush(stdout);
800}
Block * block_ptr(vaddr_t vaddr)
Definition vspace.h:1637
#define block
Definition scanner.cc:646

◆ process_info()

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

Definition at line 963 of file vspace.cc.

963 {
964 return vmem.metapage->process_info[processno];
965}

◆ send_signal()

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

Definition at line 967 of file vspace.cc.

967 {
968 if (lock)
969 lock_process(processno);
970 if (process_info(processno).sigstate != Waiting) {
971 unlock_process(processno);
972 return false;
973 }
974 if (processno == vmem.current_process) {
975 process_info(processno).sigstate = Accepted;
976 process_info(processno).signal = sig;
977 } else {
978 process_info(processno).sigstate = Pending;
979 process_info(processno).signal = sig;
980 int fd = vmem.channels[processno].fd_write;
981 char buf[1] = { 0 };
982 while (write(fd, buf, 1) != 1) {
983 }
984 }
985 if (lock)
986 unlock_process(processno);
987 return true;
988}
ProcessChannel channels[MAX_PROCESS]
Definition vspace.h:1595

◆ unlock_allocator()

static void vspace::internals::unlock_allocator ( )
static

Definition at line 770 of file vspace.cc.

770 {
771 vmem.metapage->allocator_lock.unlock();
772}

◆ unlock_file()

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

Definition at line 919 of file vspace.cc.

919 {
920 struct flock lock_info;
921 init_flock_struct(lock_info, offset, len, false);
922 fcntl(fd, F_SETLKW, &lock_info);
923}

◆ unlock_metapage()

void vspace::internals::unlock_metapage ( )

Definition at line 929 of file vspace.cc.

929 {
930 unlock_file(vmem.fd, 0);
931}
void unlock_file(int fd, size_t offset, size_t len)
Definition vspace.cc:919

◆ unlock_process()

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

Definition at line 957 of file vspace.cc.

957 {
958 unlock_file(vmem.fd,
960 + sizeof(ProcessInfo) * vmem.current_process);
961}

◆ vmem_alloc()

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

Definition at line 854 of file vspace.cc.

854 {
856 #if defined(__GNUC__) && (__GNUC__>11)
857 size_t alloc_size = size + (sizeof(vaddr_t)*2);
858 #else
859 size_t alloc_size = size + offsetof(Block, data);
860 #endif
861 int level = find_level(alloc_size);
862 int flevel = level;
863 while (flevel < LOG2_SEGMENT_SIZE && vmem.freelist[flevel] == VADDR_NULL)
864 flevel++;
865 if (vmem.freelist[flevel] == VADDR_NULL) {
866 vmem.add_segment();
867 }
869 while (flevel > level) {
870 // get and split a block
871 vaddr_t blockaddr = vmem.freelist[flevel];
872 assert((blockaddr & ((1 << flevel) - 1)) == 0);
873 Block *block = vmem.block_ptr(blockaddr);
874 vmem.freelist[flevel] = block->next;
875 if (vmem.freelist[flevel] != VADDR_NULL)
877 vaddr_t blockaddr2 = blockaddr + (1 << (flevel - 1));
878 Block *block2 = vmem.block_ptr(blockaddr2);
879 flevel--;
880 block2->next = vmem.freelist[flevel];
881 block2->prev = blockaddr;
882 block->next = blockaddr2;
883 block->prev = VADDR_NULL;
884 // block->prev == VADDR_NULL already.
885 vmem.freelist[flevel] = blockaddr;
886 }
889 vaddr_t vaddr = vmem.freelist[level];
890 #if defined(__GNUC__) && (__GNUC__>11)
891 vaddr_t result = vaddr + (sizeof(vaddr_t)*2);
892 #else
893 vaddr_t result = vaddr + offsetof(Block, data);
894 #endif
895 vmem.freelist[level] = block->next;
896 if (block->next != VADDR_NULL)
898 block->mark_as_allocated(vaddr, level);
900 memset(block->data, 0, size);
901 return result;
902}
static void lock_allocator()
Definition vspace.cc:766
static int find_level(size_t size)
Definition vspace.h:1681
static void unlock_allocator()
Definition vspace.cc:770
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 802 of file vspace.cc.

802 {
804 #if defined(__GNUC__) && (__GNUC__>11)
805 vaddr -= (sizeof(vaddr_t)*2);
806 #else
807 vaddr -= offsetof(Block, data);
808 #endif
809 vmem.ensure_is_mapped(vaddr);
810 size_t segno = vmem.segment_no(vaddr);
811 VSeg seg = vmem.segment(vaddr);
812 segaddr_t addr = vmem.segaddr(vaddr);
813 int level = seg.block_ptr(addr)->level();
814 assert(!seg.is_free(addr));
815 while (level < LOG2_SEGMENT_SIZE) {
816 segaddr_t buddy = find_buddy(addr, level);
817 Block *block = seg.block_ptr(buddy);
818 // is buddy free and at the same level?
819 if (!block->is_free() || block->level() != level)
820 break;
821 // remove buddy from freelist.
822 Block *prev = vmem.block_ptr(block->prev);
823 Block *next = vmem.block_ptr(block->next);
824 block->data[0] = level;
825 if (prev) {
826 assert(prev->next == vmem.vaddr(segno, buddy));
827 prev->next = block->next;
828 } else {
829 // head of freelist.
830 assert(vmem.freelist[level] == vmem.vaddr(segno, buddy));
831 vmem.freelist[level] = block->next;
832 }
833 if (next) {
834 assert(next->prev == vmem.vaddr(segno, buddy));
835 next->prev = block->prev;
836 }
837 // coalesce block with buddy
838 level++;
839 if (buddy < addr)
840 addr = buddy;
841 }
842 // Add coalesced block to free list
843 Block *block = seg.block_ptr(addr);
845 block->next = vmem.freelist[level];
846 block->mark_as_free(level);
847 vaddr_t blockaddr = vmem.vaddr(segno, addr);
848 if (block->next != VADDR_NULL)
849 vmem.block_ptr(block->next)->prev = blockaddr;
850 vmem.freelist[level] = blockaddr;
852}
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 1075 of file vspace.cc.

1075 {
1076 return check_signal(true, lock);
1077}
ipc_signal_t check_signal(bool resume, bool lock)
Definition vspace.cc:990

Variable Documentation

◆ config

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

Definition at line 618 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.