github.com/Ptt-official-app/go-bbs@v0.12.0/cache/systemvshm.go (about)

     1  package cache
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"runtime"
     7  	"unsafe"
     8  )
     9  
    10  // shmget: get shared memort area identifier, please see man 2 shmget
    11  func Shmget(key int, size int, flag int) (int, error) {
    12  	return shmget(key, size, flag)
    13  }
    14  
    15  // shmat: map/unmap shared memory, plase see man 2 shmat.
    16  // golang gc won't affect on this.
    17  func Shmat(shmid int, shmaddr uintptr, shmflg int) (uintptr, error) {
    18  	return shmat(shmid, shmaddr, shmflg)
    19  }
    20  
    21  // shmdt: map/unmap shared memory, plase see man 2 shmdt.
    22  func Shmdt(shmaddr uintptr) (int, error) {
    23  	return shmdt(shmaddr)
    24  }
    25  
    26  // shmctl: shared memory control operations
    27  func Shmctl(shmid int, cmd int, buf *ShmidDs) (int, error) {
    28  	return shmctl(shmid, cmd, buf)
    29  }
    30  
    31  const (
    32  	IPCCreate = 00001000
    33  
    34  	IPCRMID = 0
    35  	IPCSet  = 1
    36  	IPCStat = 2
    37  )
    38  
    39  type SHM struct {
    40  	buf []byte
    41  }
    42  
    43  func CreateKey(key int, size int) (*SHM, error) {
    44  	flag := 0
    45  	if size != 0 {
    46  		// create
    47  		flag = IPCCreate | 0600
    48  	}
    49  
    50  	shmID, err := Shmget(key, size, flag)
    51  	if err != nil {
    52  		return nil, fmt.Errorf("shmget error: %w", err)
    53  	}
    54  	// fmt.Println("shmid", shmID)
    55  	// size = 4
    56  	if size == 0 {
    57  
    58  		ds := ShmidDs{}
    59  		_, err = Shmctl(shmID, IPCStat, &ds)
    60  		if err != nil {
    61  			return nil, fmt.Errorf("shmctl error: %w", err)
    62  		}
    63  		// fmt.Printf("%+v\n", ds)
    64  		size = int(ds.ShmSegsz)
    65  	}
    66  
    67  	// v := 0
    68  
    69  	ptr, err := Shmat(shmID, uintptr(0), 0)
    70  	if err != nil {
    71  		return nil, fmt.Errorf("shmat error: %w", err)
    72  	}
    73  	// fmt.Println("ptr", *(*int)(ptr))
    74  	// fmt.Println("size", size)
    75  	b := []byte{}
    76  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    77  	hdr.Cap = size
    78  	hdr.Len = size
    79  	hdr.Data = ptr
    80  
    81  	ret := SHM{
    82  		buf: b,
    83  	}
    84  
    85  	// For GC
    86  	runtime.SetFinalizer(&ret, (*SHM).Close)
    87  	return &ret, nil
    88  }
    89  
    90  // OpenKey open a shm which is already exists.
    91  func OpenKey(key int) (*SHM, error) {
    92  	return CreateKey(key, 0)
    93  }
    94  func RemoveKey(key int) error {
    95  	shmID, err := Shmget(key, 0, 0)
    96  	if err != nil {
    97  		return fmt.Errorf("shmget error: %w", err)
    98  	}
    99  
   100  	// ds := ShmidDs{}
   101  	_, err = Shmctl(shmID, IPCRMID, nil)
   102  	if err != nil {
   103  		return fmt.Errorf("shmctl error: %w", err)
   104  	}
   105  	return nil
   106  }
   107  
   108  func (s *SHM) Bytes() []byte {
   109  	return s.buf
   110  }
   111  
   112  func (s *SHM) Close() error {
   113  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s.buf))
   114  	ptr := hdr.Data
   115  	_, err := Shmdt(ptr)
   116  
   117  	// release GC setting
   118  	runtime.SetFinalizer(s, nil)
   119  	if err != nil {
   120  		return fmt.Errorf("shmdt error: %w", err)
   121  	}
   122  	return nil
   123  }
   124  
   125  // func shmNew(key int, size int) int {
   126  
   127  // 	shmid, err := Shmget(key, size, 0)
   128  
   129  // 	shmptr := C.shmat(C.int(shmid), unsafe.Pointer(nil), 0)
   130  // 	fmt.Printf("nowValue = %d, pos = %v %v\n", *(*int)(shmptr), (*int)(shmptr), shmptr)
   131  
   132  // 	return int(shmid)
   133  
   134  // }
   135  
   136  // void * shm_new(const int key, const int size) {
   137  // 	shmid = shmget(key, size, 0);
   138  // 	printf("shmid: %d %s \n", shmid, strerror(errno));
   139  // 	if(shmid == -1){
   140  // 		// Create
   141  // 		shmid = shmget(key, size, IPC_CREAT | 0600);
   142  // 		if(shmid == -1){
   143  // 			printf("shmid: %d %s \n", shmid, strerror(errno));
   144  // 			exit(-1);
   145  // 		}
   146  // 	}
   147  
   148  // 	void * shmptr = (void *) shmat(shmid, NULL, 0);
   149  // 	if((int)shmptr == -1){
   150  // 		printf("shmat: %p %s \n", shmptr, strerror(errno));
   151  // 		exit(-2);
   152  // 	}
   153  // 	printf("nowValue = %d, pos: %p\n", *(int*)shmptr, shmptr);
   154  // 	*(int*)shmptr = *(int*)shmptr + 1;
   155  // 	return shmptr;
   156  // }
   157  
   158  // func main() {
   159  // 	shmNew(3, 4)
   160  // 	fmt.Println("OK")
   161  // }