--- /dev/null
+From ad52a67ca084d40768ad8fdf492ee26f41902670 Mon Sep 17 00:00:00 2001
+From: Charalampos Mainas <Charalampos.Mainas@neclab.eu>
+Date: Fri, 6 Sep 2019 12:08:53 +0200
+Subject: [PATCH] Use semaphores instead of futexes
+
+futexes are not implemented on Unikraft. In libgo there are some other
+targets (like openbsd) which use semaphores instead of futexes.
+Following the same approach as in these targets, with this patch
+locking is done using semaphores.
+
+---
+ libgo/go/runtime/os_linux.go | 99 ++++++++++++++++++++++++++++++++++--
+ 1 file changed, 96 insertions(+), 3 deletions(-)
+
+diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go
+index ad334869e..775f34859 100644
+--- a/libgo/go/runtime/os_linux.go
++++ b/libgo/go/runtime/os_linux.go
+@@ -9,9 +9,9 @@ import (
+ "unsafe"
+ )
+
+-type mOS struct {
+- unused byte
+-}
++//type mOS struct {
++// unused byte
++//}
+
+ func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 {
+ return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
+@@ -169,3 +169,96 @@ func sysauxv(auxv []uintptr) int {
+
+ // Temporary for gccgo until we port mem_GOOS.go.
+ var addrspace_vec [1]byte
++
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++type mOS struct {
++ waitsema uintptr // semaphore for parking on locks
++}
++
++//extern malloc
++func libc_malloc(uintptr) unsafe.Pointer
++
++//go:noescape
++//extern sem_init
++func sem_init(sem *semt, pshared int32, value uint32) int32
++
++//go:noescape
++//extern sem_wait
++func sem_wait(sem *semt) int32
++
++//go:noescape
++//extern sem_post
++func sem_post(sem *semt) int32
++
++//go:noescape
++//extern sem_timedwait
++func sem_timedwait(sem *semt, timeout *timespec) int32
++
++//go:nosplit
++func semacreate(mp *m) {
++ if mp.mos.waitsema != 0 {
++ return
++ }
++
++ var sem *semt
++
++ // Call libc's malloc rather than malloc. This will
++ // allocate space on the C heap. We can't call malloc
++ // here because it could cause a deadlock.
++ sem = (*semt)(libc_malloc(unsafe.Sizeof(*sem)))
++ if sem_init(sem, 0, 0) != 0 {
++ throw("sem_init")
++ }
++ mp.mos.waitsema = uintptr(unsafe.Pointer(sem))
++}
++
++//go:nosplit
++func semasleep(ns int64) int32 {
++ _m_ := getg().m
++ if ns >= 0 {
++ var ts timespec
++ //ts.set_sec(ns / 1000000000)
++ //ts.set_nsec(int32(ns % 1000000000))
++ ns += nanotime()
++ if sys.PtrSize == 8 {
++ ts.set_sec(ns / 1000000000)
++ ts.set_nsec(int32(ns % 1000000000))
++ } else {
++ ts.tv_nsec = 0
++ ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
++ }
++ //var nsec int32
++ //ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
++ //ts.set_nsec(nsec)
++
++ if sem_timedwait((*semt)(unsafe.Pointer(_m_.mos.waitsema)), &ts) != 0 {
++ err := errno()
++ if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
++ return -1
++ }
++ throw("sem_timedwait")
++ }
++ return 0
++ }
++ for {
++ r1 := sem_wait((*semt)(unsafe.Pointer(_m_.mos.waitsema)))
++ if r1 == 0 {
++ break
++ }
++ if errno() == _EINTR {
++ continue
++ }
++ throw("sem_wait")
++ }
++ return 0
++}
++
++//go:nosplit
++func semawakeup(mp *m) {
++ if sem_post((*semt)(unsafe.Pointer(mp.mos.waitsema))) != 0 {
++ throw("sem_post")
++ }
++}
+--
+2.17.1
+