mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 12:20:41 +00:00
Compare commits
64 Commits
v1.0.0-alp
...
v1.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b53e6e28d | ||
|
|
77bdfb2ceb | ||
|
|
2583af26d7 | ||
|
|
a38a3140dd | ||
|
|
bf8f9b8654 | ||
|
|
0ce9921c25 | ||
|
|
adc39705f3 | ||
|
|
a4f827a48d | ||
|
|
7547126570 | ||
|
|
926b44ddf6 | ||
|
|
d3771edc9d | ||
|
|
947727e33a | ||
|
|
27148981d5 | ||
|
|
6fa436e8ff | ||
|
|
2935ba3521 | ||
|
|
5c8ea6f09f | ||
|
|
c16ae57639 | ||
|
|
1c7d44fd4d | ||
|
|
ca7e38137d | ||
|
|
5936d3616c | ||
|
|
e9cfdba22a | ||
|
|
3156661e0b | ||
|
|
b4048a8eab | ||
|
|
aff73cbed7 | ||
|
|
b5244b96aa | ||
|
|
704b016f2c | ||
|
|
3b48beb428 | ||
|
|
4cbead28d5 | ||
|
|
b3f966bcaa | ||
|
|
7b54e37d12 | ||
|
|
e87ac18b84 | ||
|
|
05af87ce8e | ||
|
|
0ee61de22c | ||
|
|
1da8a6b38d | ||
|
|
b2d8237363 | ||
|
|
39f9a96b6c | ||
|
|
588c4a3508 | ||
|
|
d6734890e0 | ||
|
|
4ebb139c2b | ||
|
|
20476d2280 | ||
|
|
3131bca6ef | ||
|
|
3f91484791 | ||
|
|
a0ecd51230 | ||
|
|
dba1db9cc4 | ||
|
|
538414408d | ||
|
|
4cf05fb2e7 | ||
|
|
d9ad981c8c | ||
|
|
21c941fe63 | ||
|
|
ea2437e138 | ||
|
|
86bbc9c701 | ||
|
|
95e1d9f45f | ||
|
|
55cf9375fc | ||
|
|
654f732cd5 | ||
|
|
d4023c8b63 | ||
|
|
375f8606b4 | ||
|
|
d17e6f59fe | ||
|
|
a77d36911d | ||
|
|
4352dc4047 | ||
|
|
172356be19 | ||
|
|
08dabd51c8 | ||
|
|
bd55a58515 | ||
|
|
b646a1b8a3 | ||
|
|
6b312fa09a | ||
|
|
dad66010cd |
@@ -135,6 +135,7 @@ static void freesharedproto (lua_State *L, SharedProto *f) {
|
|||||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
|
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
|
||||||
luaM_freearray(L, f->locvars, f->sizelocvars);
|
luaM_freearray(L, f->locvars, f->sizelocvars);
|
||||||
luaM_freearray(L, f->upvalues, f->sizeupvalues);
|
luaM_freearray(L, f->upvalues, f->sizeupvalues);
|
||||||
|
luaM_free(L, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void luaF_freeproto (lua_State *L, Proto *f) {
|
void luaF_freeproto (lua_State *L, Proto *f) {
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ LUAMOD_API int (luaopen_debug) (lua_State *L);
|
|||||||
#define LUA_LOADLIBNAME "package"
|
#define LUA_LOADLIBNAME "package"
|
||||||
LUAMOD_API int (luaopen_package) (lua_State *L);
|
LUAMOD_API int (luaopen_package) (lua_State *L);
|
||||||
|
|
||||||
|
#define LUA_CACHELIB
|
||||||
|
LUAMOD_API int (luaopen_cache) (lua_State *L);
|
||||||
|
|
||||||
/* open all previous libraries */
|
/* open all previous libraries */
|
||||||
LUALIB_API void (luaL_openlibs) (lua_State *L);
|
LUALIB_API void (luaL_openlibs) (lua_State *L);
|
||||||
|
|||||||
19
HISTORY.md
19
HISTORY.md
@@ -1,3 +1,22 @@
|
|||||||
|
v1.0.0-alpha10 (2015-8-17)
|
||||||
|
-----------
|
||||||
|
* Remove the size limit of cluster RPC message.
|
||||||
|
* Remove the size limit of local message.
|
||||||
|
* Add cluster.query and clsuter.register.
|
||||||
|
* Add an option of pthread mutex lock.
|
||||||
|
* Add skynet.core.intcommand to optimize skynet.sleep etc.
|
||||||
|
* Fix a memory leak bug in lua shared proto.
|
||||||
|
* snax.msgserver use string instead of lightuserdata/size.
|
||||||
|
* Remove some unused api in netpack.
|
||||||
|
* Raise error when skynet.send to 0.
|
||||||
|
|
||||||
|
v1.0.0-alpha9 (2015-8-10)
|
||||||
|
-----------
|
||||||
|
* Improve lua serialization , support pairs metamethod.
|
||||||
|
* Bugfix : sproto (See commits log of sproto)
|
||||||
|
* Add user log service support (In config)
|
||||||
|
* Other minor bugfix (See commits log)
|
||||||
|
|
||||||
v1.0.0-alpha8 (2015-6-29)
|
v1.0.0-alpha8 (2015-6-29)
|
||||||
-----------
|
-----------
|
||||||
* Update lua 5.3.1
|
* Update lua 5.3.1
|
||||||
|
|||||||
11
Makefile
11
Makefile
@@ -5,7 +5,8 @@ CSERVICE_PATH ?= cservice
|
|||||||
|
|
||||||
SKYNET_BUILD_PATH ?= .
|
SKYNET_BUILD_PATH ?= .
|
||||||
|
|
||||||
CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
|
CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
|
||||||
|
# CFLAGS += -DUSE_PTHREAD_LOCK
|
||||||
|
|
||||||
# lua
|
# lua
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@ $(LUA_CLIB_PATH)/socketdriver.so : lualib-src/lua-socket.c | $(LUA_CLIB_PATH)
|
|||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src
|
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src
|
||||||
|
|
||||||
$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c | $(LUA_CLIB_PATH)
|
$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c | $(LUA_CLIB_PATH)
|
||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@ -Iskynet-src
|
||||||
|
|
||||||
$(LUA_CLIB_PATH)/mongo.so : lualib-src/lua-mongo.c | $(LUA_CLIB_PATH)
|
$(LUA_CLIB_PATH)/mongo.so : lualib-src/lua-mongo.c | $(LUA_CLIB_PATH)
|
||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
||||||
@@ -109,7 +110,7 @@ $(LUA_CLIB_PATH)/crypt.so : lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CL
|
|||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
||||||
|
|
||||||
$(LUA_CLIB_PATH)/sharedata.so : lualib-src/lua-sharedata.c | $(LUA_CLIB_PATH)
|
$(LUA_CLIB_PATH)/sharedata.so : lualib-src/lua-sharedata.c | $(LUA_CLIB_PATH)
|
||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||||
|
|
||||||
$(LUA_CLIB_PATH)/stm.so : lualib-src/lua-stm.c | $(LUA_CLIB_PATH)
|
$(LUA_CLIB_PATH)/stm.so : lualib-src/lua-stm.c | $(LUA_CLIB_PATH)
|
||||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||||
@@ -124,13 +125,15 @@ $(LUA_CLIB_PATH)/mysqlaux.so : lualib-src/lua-mysqlaux.c | $(LUA_CLIB_PATH)
|
|||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
||||||
|
|
||||||
$(LUA_CLIB_PATH)/debugchannel.so : lualib-src/lua-debugchannel.c | $(LUA_CLIB_PATH)
|
$(LUA_CLIB_PATH)/debugchannel.so : lualib-src/lua-debugchannel.c | $(LUA_CLIB_PATH)
|
||||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
||||||
|
|
||||||
cleanall: clean
|
cleanall: clean
|
||||||
|
ifneq (,$(wildcard 3rd/jemalloc/Makefile))
|
||||||
cd 3rd/jemalloc && $(MAKE) clean
|
cd 3rd/jemalloc && $(MAKE) clean
|
||||||
|
endif
|
||||||
cd 3rd/lua && $(MAKE) clean
|
cd 3rd/lua && $(MAKE) clean
|
||||||
rm -f $(LUA_STATICLIB)
|
rm -f $(LUA_STATICLIB)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ Run these in different console
|
|||||||
|
|
||||||
## About Lua
|
## About Lua
|
||||||
|
|
||||||
Skynet now use Lua 5.3.0 final, http://www.lua.org/ftp/lua-5.3.0.tar.gz
|
Skynet now use a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
|
||||||
|
|
||||||
|
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||||
|
|
||||||
You can also use the other official Lua version , edit the makefile by yourself .
|
You can also use the other official Lua version , edit the makefile by yourself .
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
local cluster = require "cluster"
|
local cluster = require "cluster"
|
||||||
require "skynet.manager" -- import skynet.name
|
|
||||||
local snax = require "snax"
|
local snax = require "snax"
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
local sdb = skynet.newservice("simpledb")
|
local sdb = skynet.newservice("simpledb")
|
||||||
skynet.name(".simpledb", sdb)
|
-- register name "sdb" for simpledb, you can use cluster.query() later.
|
||||||
print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
|
-- See cluster2.lua
|
||||||
print(skynet.call(".simpledb", "lua", "SET", "b", "foobar2"))
|
cluster.register("sdb", sdb)
|
||||||
print(skynet.call(".simpledb", "lua", "GET", "a"))
|
|
||||||
print(skynet.call(".simpledb", "lua", "GET", "b"))
|
print(skynet.call(sdb, "lua", "SET", "a", "foobar"))
|
||||||
|
print(skynet.call(sdb, "lua", "SET", "b", "foobar2"))
|
||||||
|
print(skynet.call(sdb, "lua", "GET", "a"))
|
||||||
|
print(skynet.call(sdb, "lua", "GET", "b"))
|
||||||
cluster.open "db"
|
cluster.open "db"
|
||||||
cluster.open "db2"
|
cluster.open "db2"
|
||||||
-- unique snax service
|
-- unique snax service
|
||||||
|
|||||||
@@ -2,10 +2,18 @@ local skynet = require "skynet"
|
|||||||
local cluster = require "cluster"
|
local cluster = require "cluster"
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
local proxy = cluster.proxy("db", ".simpledb")
|
-- query name "sdb" of cluster db.
|
||||||
print(skynet.call(proxy, "lua", "GET", "a"))
|
local sdb = cluster.query("db", "sdb")
|
||||||
print(cluster.call("db", ".simpledb", "GET", "a"))
|
print("db.sbd=",sdb)
|
||||||
print(cluster.call("db2", ".simpledb", "GET", "b"))
|
local proxy = cluster.proxy("db", sdb)
|
||||||
|
local largekey = string.rep("X", 128*1024)
|
||||||
|
local largevalue = string.rep("R", 100 * 1024)
|
||||||
|
print(skynet.call(proxy, "lua", "SET", largekey, largevalue))
|
||||||
|
local v = skynet.call(proxy, "lua", "GET", largekey)
|
||||||
|
assert(largevalue == v)
|
||||||
|
|
||||||
|
print(cluster.call("db", sdb, "GET", "a"))
|
||||||
|
print(cluster.call("db2", sdb, "GET", "b"))
|
||||||
|
|
||||||
-- test snax service
|
-- test snax service
|
||||||
local pingserver = cluster.snax("db", "pingserver")
|
local pingserver = cluster.snax("db", "pingserver")
|
||||||
|
|||||||
15
examples/config.userlog
Normal file
15
examples/config.userlog
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
root = "./"
|
||||||
|
thread = 8
|
||||||
|
logger = "userlog"
|
||||||
|
logservice = "snlua"
|
||||||
|
logpath = "."
|
||||||
|
harbor = 0
|
||||||
|
start = "main" -- main script
|
||||||
|
bootstrap = "snlua bootstrap" -- The service for bootstrap
|
||||||
|
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
|
||||||
|
lualoader = "lualib/loader.lua"
|
||||||
|
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
|
||||||
|
snax = root.."examples/?.lua;"..root.."test/?.lua"
|
||||||
|
-- snax_interface_g = "snax_g"
|
||||||
|
cpath = root.."cservice/?.so"
|
||||||
|
-- daemon = "./skynet.pid"
|
||||||
@@ -131,7 +131,7 @@ local text = "echo"
|
|||||||
local index = 1
|
local index = 1
|
||||||
|
|
||||||
print("connect")
|
print("connect")
|
||||||
local fd = assert(socket.connect("127.0.0.1", 8888))
|
fd = assert(socket.connect("127.0.0.1", 8888))
|
||||||
last = ""
|
last = ""
|
||||||
|
|
||||||
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
||||||
@@ -151,7 +151,7 @@ socket.close(fd)
|
|||||||
index = index + 1
|
index = index + 1
|
||||||
|
|
||||||
print("connect again")
|
print("connect again")
|
||||||
local fd = assert(socket.connect("127.0.0.1", 8888))
|
fd = assert(socket.connect("127.0.0.1", 8888))
|
||||||
last = ""
|
last = ""
|
||||||
|
|
||||||
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ function server.login_handler(uid, secret)
|
|||||||
end
|
end
|
||||||
|
|
||||||
internal_id = internal_id + 1
|
internal_id = internal_id + 1
|
||||||
local username = msgserver.username(uid, internal_id, servername)
|
local id = internal_id -- don't use internal_id directly
|
||||||
|
local username = msgserver.username(uid, id, servername)
|
||||||
|
|
||||||
-- you can use a pool to alloc new agent
|
-- you can use a pool to alloc new agent
|
||||||
local agent = skynet.newservice "msgagent"
|
local agent = skynet.newservice "msgagent"
|
||||||
@@ -25,11 +26,11 @@ function server.login_handler(uid, secret)
|
|||||||
username = username,
|
username = username,
|
||||||
agent = agent,
|
agent = agent,
|
||||||
uid = uid,
|
uid = uid,
|
||||||
subid = internal_id,
|
subid = id,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- trash subid (no used)
|
-- trash subid (no used)
|
||||||
skynet.call(agent, "lua", "login", uid, internal_id, secret)
|
skynet.call(agent, "lua", "login", uid, id, secret)
|
||||||
|
|
||||||
users[uid] = u
|
users[uid] = u
|
||||||
username_map[username] = u
|
username_map[username] = u
|
||||||
@@ -37,7 +38,7 @@ function server.login_handler(uid, secret)
|
|||||||
msgserver.login(username, secret)
|
msgserver.login(username, secret)
|
||||||
|
|
||||||
-- you should return unique subid
|
-- you should return unique subid
|
||||||
return internal_id
|
return id
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call by agent
|
-- call by agent
|
||||||
@@ -73,9 +74,9 @@ function server.disconnect_handler(username)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- call by self (when recv a request from client)
|
-- call by self (when recv a request from client)
|
||||||
function server.request_handler(username, msg, sz)
|
function server.request_handler(username, msg)
|
||||||
local u = username_map[username]
|
local u = username_map[username]
|
||||||
return skynet.tostring(skynet.rawcall(u.agent, "client", msg, sz))
|
return skynet.tostring(skynet.rawcall(u.agent, "client", msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call by self (when gate open)
|
-- call by self (when gate open)
|
||||||
|
|||||||
@@ -37,6 +37,16 @@ skynet.start(function()
|
|||||||
skynet.error(string.format("b[%d]=%s", k,v))
|
skynet.error(string.format("b[%d]=%s", k,v))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- test lua serialization
|
||||||
|
local s = skynet.packstring(obj)
|
||||||
|
local nobj = skynet.unpack(s)
|
||||||
|
for k,v in pairs(nobj) do
|
||||||
|
skynet.error(string.format("nobj[%s]=%s", k,v))
|
||||||
|
end
|
||||||
|
for k,v in ipairs(nobj.b) do
|
||||||
|
skynet.error(string.format("nobj.b[%d]=%s", k,v))
|
||||||
|
end
|
||||||
|
|
||||||
for i = 1, 5 do
|
for i = 1, 5 do
|
||||||
skynet.sleep(100)
|
skynet.sleep(100)
|
||||||
skynet.error("second " ..i)
|
skynet.error("second " ..i)
|
||||||
|
|||||||
15
examples/userlog.lua
Normal file
15
examples/userlog.lua
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager"
|
||||||
|
|
||||||
|
skynet.register_protocol {
|
||||||
|
name = "text",
|
||||||
|
id = skynet.PTYPE_TEXT,
|
||||||
|
unpack = skynet.tostring,
|
||||||
|
dispatch = function(_, address, msg)
|
||||||
|
print(string.format("%x(%.2f): %s", address, skynet.time(), msg))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
skynet.start(function()
|
||||||
|
skynet.register ".logger"
|
||||||
|
end)
|
||||||
@@ -32,6 +32,11 @@ function SOCKET.error(fd, msg)
|
|||||||
close_agent(fd)
|
close_agent(fd)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function SOCKET.warning(fd, size)
|
||||||
|
-- size K bytes havn't send out in fd
|
||||||
|
print("socket warning", fd, size)
|
||||||
|
end
|
||||||
|
|
||||||
function SOCKET.data(fd, msg)
|
function SOCKET.data(fd, msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
#define DEFAULT_CAP 64
|
#define DEFAULT_CAP 64
|
||||||
#define MAX_NUMBER 1024
|
#define MAX_NUMBER 1024
|
||||||
@@ -243,12 +244,16 @@ append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
|||||||
write_string(bs, key, sz);
|
write_string(bs, key, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_32bit(int64_t v) {
|
||||||
|
return v >= INT32_MIN && v <= INT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||||
if (lua_isinteger(L, -1)) {
|
if (lua_isinteger(L, -1)) {
|
||||||
int64_t i = lua_tointeger(L, -1);
|
int64_t i = lua_tointeger(L, -1);
|
||||||
int si = i >> 31;
|
if (is_32bit(i)) {
|
||||||
if (si == 0 || si == -1) {
|
|
||||||
append_key(bs, BSON_INT32, key, sz);
|
append_key(bs, BSON_INT32, key, sz);
|
||||||
write_int32(bs, i);
|
write_int32(bs, i);
|
||||||
} else {
|
} else {
|
||||||
@@ -1136,7 +1141,7 @@ lobjectid(lua_State *L) {
|
|||||||
} else {
|
} else {
|
||||||
time_t ti = time(NULL);
|
time_t ti = time(NULL);
|
||||||
// old_counter is a static var, use atom inc.
|
// old_counter is a static var, use atom inc.
|
||||||
uint32_t id = __sync_fetch_and_add(&oid_counter,1);
|
uint32_t id = ATOM_FINC(&oid_counter);
|
||||||
|
|
||||||
oid[2] = (ti>>24) & 0xff;
|
oid[2] = (ti>>24) & 0xff;
|
||||||
oid[3] = (ti>>16) & 0xff;
|
oid[3] = (ti>>16) & 0xff;
|
||||||
|
|||||||
@@ -128,11 +128,8 @@ lusleep(lua_State *L) {
|
|||||||
|
|
||||||
#define QUEUE_SIZE 1024
|
#define QUEUE_SIZE 1024
|
||||||
|
|
||||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
|
||||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
|
||||||
|
|
||||||
struct queue {
|
struct queue {
|
||||||
int lock;
|
pthread_mutex_t lock;
|
||||||
int head;
|
int head;
|
||||||
int tail;
|
int tail;
|
||||||
char * queue[QUEUE_SIZE];
|
char * queue[QUEUE_SIZE];
|
||||||
@@ -153,7 +150,7 @@ readline_stdin(void * arg) {
|
|||||||
memcpy(str, tmp, n);
|
memcpy(str, tmp, n);
|
||||||
str[n] = 0;
|
str[n] = 0;
|
||||||
|
|
||||||
LOCK(q);
|
pthread_mutex_lock(&q->lock);
|
||||||
q->queue[q->tail] = str;
|
q->queue[q->tail] = str;
|
||||||
|
|
||||||
if (++q->tail >= QUEUE_SIZE) {
|
if (++q->tail >= QUEUE_SIZE) {
|
||||||
@@ -163,7 +160,7 @@ readline_stdin(void * arg) {
|
|||||||
// queue overflow
|
// queue overflow
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
UNLOCK(q);
|
pthread_mutex_unlock(&q->lock);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -171,16 +168,16 @@ readline_stdin(void * arg) {
|
|||||||
static int
|
static int
|
||||||
lreadstdin(lua_State *L) {
|
lreadstdin(lua_State *L) {
|
||||||
struct queue *q = lua_touserdata(L, lua_upvalueindex(1));
|
struct queue *q = lua_touserdata(L, lua_upvalueindex(1));
|
||||||
LOCK(q);
|
pthread_mutex_lock(&q->lock);
|
||||||
if (q->head == q->tail) {
|
if (q->head == q->tail) {
|
||||||
UNLOCK(q);
|
pthread_mutex_unlock(&q->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
char * str = q->queue[q->head];
|
char * str = q->queue[q->head];
|
||||||
if (++q->head >= QUEUE_SIZE) {
|
if (++q->head >= QUEUE_SIZE) {
|
||||||
q->head = 0;
|
q->head = 0;
|
||||||
}
|
}
|
||||||
UNLOCK(q);
|
pthread_mutex_unlock(&q->lock);
|
||||||
lua_pushstring(L, str);
|
lua_pushstring(L, str);
|
||||||
free(str);
|
free(str);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -201,6 +198,7 @@ luaopen_clientsocket(lua_State *L) {
|
|||||||
|
|
||||||
struct queue * q = lua_newuserdata(L, sizeof(*q));
|
struct queue * q = lua_newuserdata(L, sizeof(*q));
|
||||||
memset(q, 0, sizeof(*q));
|
memset(q, 0, sizeof(*q));
|
||||||
|
pthread_mutex_init(&q->lock, NULL);
|
||||||
lua_pushcclosure(L, lreadstdin, 1);
|
lua_pushcclosure(L, lreadstdin, 1);
|
||||||
lua_setfield(L, -2, "readstdin");
|
lua_setfield(L, -2, "readstdin");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
|
|
||||||
@@ -15,7 +16,8 @@
|
|||||||
uint32_t next_session
|
uint32_t next_session
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TEMP_LENGTH 0x10007
|
#define TEMP_LENGTH 0x8200
|
||||||
|
#define MULTI_PART 0x8000
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_uint32(uint8_t * buf, uint32_t n) {
|
fill_uint32(uint8_t * buf, uint32_t n) {
|
||||||
@@ -26,30 +28,75 @@ fill_uint32(uint8_t * buf, uint32_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
|
fill_header(lua_State *L, uint8_t *buf, int sz) {
|
||||||
if (sz >= 0x10000) {
|
assert(sz < 0x10000);
|
||||||
skynet_free(msg);
|
|
||||||
luaL_error(L, "request message is too long %d", sz);
|
|
||||||
}
|
|
||||||
buf[0] = (sz >> 8) & 0xff;
|
buf[0] = (sz >> 8) & 0xff;
|
||||||
buf[1] = sz & 0xff;
|
buf[1] = sz & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*
|
||||||
packreq_number(lua_State *L, int session, void * msg, size_t sz) {
|
The request package :
|
||||||
|
size <= 0x8000 (32K) and address is id
|
||||||
|
WORD sz+9
|
||||||
|
BYTE 0
|
||||||
|
DWORD addr
|
||||||
|
DWORD session
|
||||||
|
PADDING msg(sz)
|
||||||
|
size > 0x8000 and address is id
|
||||||
|
DWORD 13
|
||||||
|
BYTE 1 ; multireq
|
||||||
|
DWORD addr
|
||||||
|
DWORD session
|
||||||
|
DWORD sz
|
||||||
|
|
||||||
|
size <= 0x8000 (32K) and address is string
|
||||||
|
WORD sz+6+namelen
|
||||||
|
BYTE 0x80
|
||||||
|
BYTE namelen
|
||||||
|
STRING name
|
||||||
|
DWORD session
|
||||||
|
PADDING msg(sz)
|
||||||
|
size > 0x8000 and address is string
|
||||||
|
DWORD 10 + namelen
|
||||||
|
BYTE 0x81
|
||||||
|
BYTE namelen
|
||||||
|
STRING name
|
||||||
|
DWORD session
|
||||||
|
DWORD sz
|
||||||
|
|
||||||
|
multi req
|
||||||
|
WORD sz + 5
|
||||||
|
BYTE 2/3 ; 2:multipart, 3:multipart end
|
||||||
|
DWORD SESSION
|
||||||
|
PADDING msgpart(sz)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
|
||||||
uint32_t addr = (uint32_t)lua_tointeger(L,1);
|
uint32_t addr = (uint32_t)lua_tointeger(L,1);
|
||||||
uint8_t buf[TEMP_LENGTH];
|
uint8_t buf[TEMP_LENGTH];
|
||||||
fill_header(L, buf, sz+9, msg);
|
if (sz < MULTI_PART) {
|
||||||
buf[2] = 0;
|
fill_header(L, buf, sz+9);
|
||||||
fill_uint32(buf+3, addr);
|
buf[2] = 0;
|
||||||
fill_uint32(buf+7, (uint32_t)session);
|
fill_uint32(buf+3, addr);
|
||||||
memcpy(buf+11,msg,sz);
|
fill_uint32(buf+7, (uint32_t)session);
|
||||||
|
memcpy(buf+11,msg,sz);
|
||||||
|
|
||||||
lua_pushlstring(L, (const char *)buf, sz+11);
|
lua_pushlstring(L, (const char *)buf, sz+11);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
int part = (sz - 1) / MULTI_PART + 1;
|
||||||
|
fill_header(L, buf, 13);
|
||||||
|
buf[2] = 1;
|
||||||
|
fill_uint32(buf+3, addr);
|
||||||
|
fill_uint32(buf+7, (uint32_t)session);
|
||||||
|
fill_uint32(buf+11, sz);
|
||||||
|
lua_pushlstring(L, (const char *)buf, 15);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
packreq_string(lua_State *L, int session, void * msg, size_t sz) {
|
packreq_string(lua_State *L, int session, void * msg, uint32_t sz) {
|
||||||
size_t namelen = 0;
|
size_t namelen = 0;
|
||||||
const char *name = lua_tolstring(L, 1, &namelen);
|
const char *name = lua_tolstring(L, 1, &namelen);
|
||||||
if (name == NULL || namelen < 1 || namelen > 255) {
|
if (name == NULL || namelen < 1 || namelen > 255) {
|
||||||
@@ -58,13 +105,53 @@ packreq_string(lua_State *L, int session, void * msg, size_t sz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[TEMP_LENGTH];
|
uint8_t buf[TEMP_LENGTH];
|
||||||
fill_header(L, buf, sz+5+namelen, msg);
|
if (sz < MULTI_PART) {
|
||||||
buf[2] = (uint8_t)namelen;
|
fill_header(L, buf, sz+6+namelen);
|
||||||
memcpy(buf+3, name, namelen);
|
buf[2] = 0x80;
|
||||||
fill_uint32(buf+3+namelen, (uint32_t)session);
|
buf[3] = (uint8_t)namelen;
|
||||||
memcpy(buf+7+namelen,msg,sz);
|
memcpy(buf+4, name, namelen);
|
||||||
|
fill_uint32(buf+4+namelen, (uint32_t)session);
|
||||||
|
memcpy(buf+8+namelen,msg,sz);
|
||||||
|
|
||||||
lua_pushlstring(L, (const char *)buf, sz+7+namelen);
|
lua_pushlstring(L, (const char *)buf, sz+8+namelen);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
int part = (sz - 1) / MULTI_PART + 1;
|
||||||
|
fill_header(L, buf, 10+namelen);
|
||||||
|
buf[2] = 0x81;
|
||||||
|
buf[3] = (uint8_t)namelen;
|
||||||
|
memcpy(buf+4, name, namelen);
|
||||||
|
fill_uint32(buf+4+namelen, (uint32_t)session);
|
||||||
|
fill_uint32(buf+8+namelen, sz);
|
||||||
|
|
||||||
|
lua_pushlstring(L, (const char *)buf, 12+namelen);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
packreq_multi(lua_State *L, int session, void * msg, uint32_t sz) {
|
||||||
|
uint8_t buf[TEMP_LENGTH];
|
||||||
|
int part = (sz - 1) / MULTI_PART + 1;
|
||||||
|
int i;
|
||||||
|
char *ptr = msg;
|
||||||
|
for (i=0;i<part;i++) {
|
||||||
|
uint32_t s;
|
||||||
|
if (sz > MULTI_PART) {
|
||||||
|
s = MULTI_PART;
|
||||||
|
buf[2] = 2;
|
||||||
|
} else {
|
||||||
|
s = sz;
|
||||||
|
buf[2] = 3; // the last multi part
|
||||||
|
}
|
||||||
|
fill_header(L, buf, s+5);
|
||||||
|
fill_uint32(buf+3, (uint32_t)session);
|
||||||
|
memcpy(buf+7, ptr, s);
|
||||||
|
lua_pushlstring(L, (const char *)buf, s+7);
|
||||||
|
lua_rawseti(L, -2, i+1);
|
||||||
|
sz -= s;
|
||||||
|
ptr += s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -73,23 +160,33 @@ lpackrequest(lua_State *L) {
|
|||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
return luaL_error(L, "Invalid request message");
|
return luaL_error(L, "Invalid request message");
|
||||||
}
|
}
|
||||||
size_t sz = (size_t)luaL_checkinteger(L,4);
|
uint32_t sz = (uint32_t)luaL_checkinteger(L,4);
|
||||||
int session = luaL_checkinteger(L,2);
|
int session = luaL_checkinteger(L,2);
|
||||||
if (session <= 0) {
|
if (session <= 0) {
|
||||||
|
skynet_free(msg);
|
||||||
return luaL_error(L, "Invalid request session %d", session);
|
return luaL_error(L, "Invalid request session %d", session);
|
||||||
}
|
}
|
||||||
int addr_type = lua_type(L,1);
|
int addr_type = lua_type(L,1);
|
||||||
|
int multipak;
|
||||||
if (addr_type == LUA_TNUMBER) {
|
if (addr_type == LUA_TNUMBER) {
|
||||||
packreq_number(L, session, msg, sz);
|
multipak = packreq_number(L, session, msg, sz);
|
||||||
} else {
|
} else {
|
||||||
packreq_string(L, session, msg, sz);
|
multipak = packreq_string(L, session, msg, sz);
|
||||||
}
|
}
|
||||||
|
int current_session = session;
|
||||||
if (++session < 0) {
|
if (++session < 0) {
|
||||||
session = 1;
|
session = 1;
|
||||||
}
|
}
|
||||||
skynet_free(msg);
|
|
||||||
lua_pushinteger(L, session);
|
lua_pushinteger(L, session);
|
||||||
return 2;
|
if (multipak) {
|
||||||
|
lua_createtable(L, multipak, 0);
|
||||||
|
packreq_multi(L, current_session, msg, sz);
|
||||||
|
skynet_free(msg);
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
skynet_free(msg);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -98,6 +195,7 @@ lpackrequest(lua_State *L) {
|
|||||||
uint32_t or string addr
|
uint32_t or string addr
|
||||||
int session
|
int session
|
||||||
string msg
|
string msg
|
||||||
|
boolean padding
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
@@ -106,44 +204,122 @@ unpack_uint32(const uint8_t * buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unpackreq_number(lua_State *L, const uint8_t * buf, size_t sz) {
|
unpackreq_number(lua_State *L, const uint8_t * buf, int sz) {
|
||||||
if (sz < 9) {
|
if (sz < 9) {
|
||||||
return luaL_error(L, "Invalid cluster message");
|
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
|
||||||
}
|
}
|
||||||
uint32_t address = unpack_uint32(buf+1);
|
uint32_t address = unpack_uint32(buf+1);
|
||||||
uint32_t session = unpack_uint32(buf+5);
|
uint32_t session = unpack_uint32(buf+5);
|
||||||
lua_pushinteger(L, (uint32_t)address);
|
lua_pushinteger(L, address);
|
||||||
lua_pushinteger(L, (uint32_t)session);
|
lua_pushinteger(L, session);
|
||||||
lua_pushlstring(L, (const char *)buf+9, sz-9);
|
lua_pushlstring(L, (const char *)buf+9, sz-9);
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unpackreq_string(lua_State *L, const uint8_t * buf, size_t sz) {
|
unpackmreq_number(lua_State *L, const uint8_t * buf, int sz) {
|
||||||
size_t namesz = buf[0];
|
if (sz != 13) {
|
||||||
if (sz < namesz + 5) {
|
return luaL_error(L, "Invalid cluster message size %d (multi req must be 13)", sz);
|
||||||
return luaL_error(L, "Invalid cluster message");
|
|
||||||
}
|
}
|
||||||
lua_pushlstring(L, (const char *)buf+1, namesz);
|
uint32_t address = unpack_uint32(buf+1);
|
||||||
uint32_t session = unpack_uint32(buf + namesz + 1);
|
uint32_t session = unpack_uint32(buf+5);
|
||||||
|
uint32_t size = unpack_uint32(buf+9);
|
||||||
|
lua_pushinteger(L, address);
|
||||||
|
lua_pushinteger(L, session);
|
||||||
|
lua_pushinteger(L, size);
|
||||||
|
lua_pushboolean(L, 1); // padding multi part
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
unpackmreq_part(lua_State *L, const uint8_t * buf, int sz) {
|
||||||
|
if (sz < 5) {
|
||||||
|
return luaL_error(L, "Invalid cluster multi part message");
|
||||||
|
}
|
||||||
|
int padding = (buf[0] == 2);
|
||||||
|
uint32_t session = unpack_uint32(buf+1);
|
||||||
|
lua_pushboolean(L, 0); // no address
|
||||||
|
lua_pushinteger(L, session);
|
||||||
|
lua_pushlstring(L, (const char *)buf+5, sz-5);
|
||||||
|
lua_pushboolean(L, padding);
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
unpackreq_string(lua_State *L, const uint8_t * buf, int sz) {
|
||||||
|
if (sz < 2) {
|
||||||
|
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
|
||||||
|
}
|
||||||
|
size_t namesz = buf[1];
|
||||||
|
if (sz < namesz + 6) {
|
||||||
|
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
|
||||||
|
}
|
||||||
|
lua_pushlstring(L, (const char *)buf+2, namesz);
|
||||||
|
uint32_t session = unpack_uint32(buf + namesz + 2);
|
||||||
lua_pushinteger(L, (uint32_t)session);
|
lua_pushinteger(L, (uint32_t)session);
|
||||||
lua_pushlstring(L, (const char *)buf+1+namesz+4, sz - namesz - 5);
|
lua_pushlstring(L, (const char *)buf+2+namesz+4, sz - namesz - 6);
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
unpackmreq_string(lua_State *L, const uint8_t * buf, int sz) {
|
||||||
|
if (sz < 2) {
|
||||||
|
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
|
||||||
|
}
|
||||||
|
size_t namesz = buf[1];
|
||||||
|
if (sz < namesz + 10) {
|
||||||
|
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
|
||||||
|
}
|
||||||
|
lua_pushlstring(L, (const char *)buf+2, namesz);
|
||||||
|
uint32_t session = unpack_uint32(buf + namesz + 2);
|
||||||
|
uint32_t size = unpack_uint32(buf + namesz + 6);
|
||||||
|
lua_pushinteger(L, session);
|
||||||
|
lua_pushinteger(L, size);
|
||||||
|
lua_pushboolean(L, 1); // padding multipart
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lunpackrequest(lua_State *L) {
|
lunpackrequest(lua_State *L) {
|
||||||
size_t sz;
|
size_t ssz;
|
||||||
const char *msg = luaL_checklstring(L,1,&sz);
|
const char *msg = luaL_checklstring(L,1,&ssz);
|
||||||
if (msg[0] == 0) {
|
int sz = (int)ssz;
|
||||||
|
switch (msg[0]) {
|
||||||
|
case 0:
|
||||||
return unpackreq_number(L, (const uint8_t *)msg, sz);
|
return unpackreq_number(L, (const uint8_t *)msg, sz);
|
||||||
} else {
|
case 1:
|
||||||
|
return unpackmreq_number(L, (const uint8_t *)msg, sz);
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
return unpackmreq_part(L, (const uint8_t *)msg, sz);
|
||||||
|
case '\x80':
|
||||||
return unpackreq_string(L, (const uint8_t *)msg, sz);
|
return unpackreq_string(L, (const uint8_t *)msg, sz);
|
||||||
|
case '\x81':
|
||||||
|
return unpackmreq_string(L, (const uint8_t *)msg, sz);
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "Invalid req package type %d", msg[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
DWORD session
|
||||||
|
BYTE type
|
||||||
|
0: error
|
||||||
|
1: ok
|
||||||
|
2: multi begin
|
||||||
|
3: multi part
|
||||||
|
4: multi end
|
||||||
|
PADDING msg
|
||||||
|
type = 0, error msg
|
||||||
|
type = 1, msg
|
||||||
|
type = 2, DWORD size
|
||||||
|
type = 3/4, msg
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
int session
|
int session
|
||||||
boolean ok
|
boolean ok
|
||||||
@@ -162,16 +338,56 @@ lpackresponse(lua_State *L) {
|
|||||||
|
|
||||||
if (lua_type(L,3) == LUA_TSTRING) {
|
if (lua_type(L,3) == LUA_TSTRING) {
|
||||||
msg = (void *)lua_tolstring(L, 3, &sz);
|
msg = (void *)lua_tolstring(L, 3, &sz);
|
||||||
if (sz > 0x1000) {
|
|
||||||
sz = 0x1000;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
msg = lua_touserdata(L,3);
|
msg = lua_touserdata(L,3);
|
||||||
sz = (size_t)luaL_checkinteger(L, 4);
|
sz = (size_t)luaL_checkinteger(L, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
if (sz > MULTI_PART) {
|
||||||
|
// truncate the error msg if too long
|
||||||
|
sz = MULTI_PART;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sz > MULTI_PART) {
|
||||||
|
// return
|
||||||
|
int part = (sz - 1) / MULTI_PART + 1;
|
||||||
|
lua_createtable(L, part+1, 0);
|
||||||
|
uint8_t buf[TEMP_LENGTH];
|
||||||
|
|
||||||
|
// multi part begin
|
||||||
|
fill_header(L, buf, 9);
|
||||||
|
fill_uint32(buf+2, session);
|
||||||
|
buf[6] = 2;
|
||||||
|
fill_uint32(buf+7, (uint32_t)sz);
|
||||||
|
lua_pushlstring(L, (const char *)buf, 11);
|
||||||
|
lua_rawseti(L, -2, 1);
|
||||||
|
|
||||||
|
char * ptr = msg;
|
||||||
|
int i;
|
||||||
|
for (i=0;i<part;i++) {
|
||||||
|
int s;
|
||||||
|
if (sz > MULTI_PART) {
|
||||||
|
s = MULTI_PART;
|
||||||
|
buf[6] = 3;
|
||||||
|
} else {
|
||||||
|
s = sz;
|
||||||
|
buf[6] = 4;
|
||||||
|
}
|
||||||
|
fill_header(L, buf, s+5);
|
||||||
|
fill_uint32(buf+2, session);
|
||||||
|
memcpy(buf+7,ptr,s);
|
||||||
|
lua_pushlstring(L, (const char *)buf, s+7);
|
||||||
|
lua_rawseti(L, -2, i+2);
|
||||||
|
sz -= s;
|
||||||
|
ptr += s;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t buf[TEMP_LENGTH];
|
uint8_t buf[TEMP_LENGTH];
|
||||||
fill_header(L, buf, sz+5, msg);
|
fill_header(L, buf, sz+5);
|
||||||
fill_uint32(buf+2, session);
|
fill_uint32(buf+2, session);
|
||||||
buf[6] = ok;
|
buf[6] = ok;
|
||||||
memcpy(buf+7,msg,sz);
|
memcpy(buf+7,msg,sz);
|
||||||
@@ -186,6 +402,7 @@ lpackresponse(lua_State *L) {
|
|||||||
return integer session
|
return integer session
|
||||||
boolean ok
|
boolean ok
|
||||||
string msg
|
string msg
|
||||||
|
boolean padding
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lunpackresponse(lua_State *L) {
|
lunpackresponse(lua_State *L) {
|
||||||
@@ -196,10 +413,66 @@ lunpackresponse(lua_State *L) {
|
|||||||
}
|
}
|
||||||
uint32_t session = unpack_uint32((const uint8_t *)buf);
|
uint32_t session = unpack_uint32((const uint8_t *)buf);
|
||||||
lua_pushinteger(L, (lua_Integer)session);
|
lua_pushinteger(L, (lua_Integer)session);
|
||||||
lua_pushboolean(L, buf[4]);
|
switch(buf[4]) {
|
||||||
lua_pushlstring(L, buf+5, sz-5);
|
case 0: // error
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
lua_pushlstring(L, buf+5, sz-5);
|
||||||
|
return 3;
|
||||||
|
case 1: // ok
|
||||||
|
case 4: // multi end
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
lua_pushlstring(L, buf+5, sz-5);
|
||||||
|
return 3;
|
||||||
|
case 2: // multi begin
|
||||||
|
if (sz != 9) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sz = unpack_uint32((const uint8_t *)buf+5);
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
lua_pushinteger(L, sz);
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 4;
|
||||||
|
case 3: // multi part
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
lua_pushlstring(L, buf+5, sz-5);
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 3;
|
static int
|
||||||
|
lconcat(lua_State *L) {
|
||||||
|
if (!lua_istable(L,1))
|
||||||
|
return 0;
|
||||||
|
if (lua_geti(L,1,1) != LUA_TNUMBER)
|
||||||
|
return 0;
|
||||||
|
int sz = lua_tointeger(L,-1);
|
||||||
|
lua_pop(L,1);
|
||||||
|
char * buff = skynet_malloc(sz);
|
||||||
|
int idx = 2;
|
||||||
|
int offset = 0;
|
||||||
|
while(lua_geti(L,1,idx) == LUA_TSTRING) {
|
||||||
|
size_t s;
|
||||||
|
const char * str = lua_tolstring(L, -1, &s);
|
||||||
|
if (s+offset > sz) {
|
||||||
|
skynet_free(buff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(buff+offset, str, s);
|
||||||
|
lua_pop(L,1);
|
||||||
|
offset += s;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
if (offset != sz) {
|
||||||
|
skynet_free(buff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// buff/sz will send to other service, See clusterd.lua
|
||||||
|
lua_pushlightuserdata(L, buff);
|
||||||
|
lua_pushinteger(L, sz);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -209,6 +482,7 @@ luaopen_cluster_core(lua_State *L) {
|
|||||||
{ "unpackrequest", lunpackrequest },
|
{ "unpackrequest", lunpackrequest },
|
||||||
{ "packresponse", lpackresponse },
|
{ "packresponse", lpackresponse },
|
||||||
{ "unpackresponse", lunpackresponse },
|
{ "unpackresponse", lunpackresponse },
|
||||||
|
{ "concat", lconcat },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
luaL_checkversion(L);
|
luaL_checkversion(L);
|
||||||
|
|||||||
@@ -4,10 +4,9 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#define METANAME "debugchannel"
|
#define METANAME "debugchannel"
|
||||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
|
||||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
|
||||||
|
|
||||||
struct command {
|
struct command {
|
||||||
struct command * next;
|
struct command * next;
|
||||||
@@ -15,7 +14,7 @@ struct command {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct channel {
|
struct channel {
|
||||||
int lock;
|
struct spinlock lock;
|
||||||
int ref;
|
int ref;
|
||||||
struct command * head;
|
struct command * head;
|
||||||
struct command * tail;
|
struct command * tail;
|
||||||
@@ -26,6 +25,7 @@ channel_new() {
|
|||||||
struct channel * c = malloc(sizeof(*c));
|
struct channel * c = malloc(sizeof(*c));
|
||||||
memset(c, 0 , sizeof(*c));
|
memset(c, 0 , sizeof(*c));
|
||||||
c->ref = 1;
|
c->ref = 1;
|
||||||
|
SPIN_INIT(c)
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -33,21 +33,21 @@ channel_new() {
|
|||||||
static struct channel *
|
static struct channel *
|
||||||
channel_connect(struct channel *c) {
|
channel_connect(struct channel *c) {
|
||||||
struct channel * ret = NULL;
|
struct channel * ret = NULL;
|
||||||
LOCK(c)
|
SPIN_LOCK(c)
|
||||||
if (c->ref == 1) {
|
if (c->ref == 1) {
|
||||||
++c->ref;
|
++c->ref;
|
||||||
ret = c;
|
ret = c;
|
||||||
}
|
}
|
||||||
UNLOCK(c)
|
SPIN_UNLOCK(c)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct channel *
|
static struct channel *
|
||||||
channel_release(struct channel *c) {
|
channel_release(struct channel *c) {
|
||||||
LOCK(c)
|
SPIN_LOCK(c)
|
||||||
--c->ref;
|
--c->ref;
|
||||||
if (c->ref > 0) {
|
if (c->ref > 0) {
|
||||||
UNLOCK(c)
|
SPIN_UNLOCK(c)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
// never unlock while reference is 0
|
// never unlock while reference is 0
|
||||||
@@ -59,6 +59,8 @@ channel_release(struct channel *c) {
|
|||||||
free(p);
|
free(p);
|
||||||
p = next;
|
p = next;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(c)
|
||||||
|
SPIN_DESTROY(c)
|
||||||
free(c);
|
free(c);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -67,9 +69,9 @@ channel_release(struct channel *c) {
|
|||||||
static struct command *
|
static struct command *
|
||||||
channel_read(struct channel *c, double timeout) {
|
channel_read(struct channel *c, double timeout) {
|
||||||
struct command * ret = NULL;
|
struct command * ret = NULL;
|
||||||
LOCK(c)
|
SPIN_LOCK(c)
|
||||||
if (c->head == NULL) {
|
if (c->head == NULL) {
|
||||||
UNLOCK(c)
|
SPIN_UNLOCK(c)
|
||||||
int ti = (int)(timeout * 100000);
|
int ti = (int)(timeout * 100000);
|
||||||
usleep(ti);
|
usleep(ti);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -79,7 +81,7 @@ channel_read(struct channel *c, double timeout) {
|
|||||||
if (c->head == NULL) {
|
if (c->head == NULL) {
|
||||||
c->tail = NULL;
|
c->tail = NULL;
|
||||||
}
|
}
|
||||||
UNLOCK(c)
|
SPIN_UNLOCK(c)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -90,14 +92,14 @@ channel_write(struct channel *c, const char * s, size_t sz) {
|
|||||||
cmd->sz = sz;
|
cmd->sz = sz;
|
||||||
cmd->next = NULL;
|
cmd->next = NULL;
|
||||||
memcpy(cmd+1, s, sz);
|
memcpy(cmd+1, s, sz);
|
||||||
LOCK(c)
|
SPIN_LOCK(c)
|
||||||
if (c->tail == NULL) {
|
if (c->tail == NULL) {
|
||||||
c->head = c->tail = cmd;
|
c->head = c->tail = cmd;
|
||||||
} else {
|
} else {
|
||||||
c->tail->next = cmd;
|
c->tail->next = cmd;
|
||||||
c->tail = cmd;
|
c->tail = cmd;
|
||||||
}
|
}
|
||||||
UNLOCK(c)
|
SPIN_UNLOCK(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct channel_box {
|
struct channel_box {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ luaopen_memory(lua_State *L) {
|
|||||||
{ "block", lblock },
|
{ "block", lblock },
|
||||||
{ "dumpinfo", ldumpinfo },
|
{ "dumpinfo", ldumpinfo },
|
||||||
{ "dump", ldump },
|
{ "dump", ldump },
|
||||||
|
{ "info", dump_mem_lua },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
struct mc_package {
|
struct mc_package {
|
||||||
int reference;
|
int reference;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@@ -116,7 +118,7 @@ static int
|
|||||||
mc_closelocal(lua_State *L) {
|
mc_closelocal(lua_State *L) {
|
||||||
struct mc_package *pack = lua_touserdata(L,1);
|
struct mc_package *pack = lua_touserdata(L,1);
|
||||||
|
|
||||||
int ref = __sync_sub_and_fetch(&pack->reference, 1);
|
int ref = ATOM_DEC(&pack->reference);
|
||||||
if (ref <= 0) {
|
if (ref <= 0) {
|
||||||
skynet_free(pack->data);
|
skynet_free(pack->data);
|
||||||
skynet_free(pack);
|
skynet_free(pack);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define TYPE_ERROR 3
|
#define TYPE_ERROR 3
|
||||||
#define TYPE_OPEN 4
|
#define TYPE_OPEN 4
|
||||||
#define TYPE_CLOSE 5
|
#define TYPE_CLOSE 5
|
||||||
|
#define TYPE_WARNING 6
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Each package is uint16 + data , uint16 (serialized in big-endian) is the number of bytes comprising the data .
|
Each package is uint16 + data , uint16 (serialized in big-endian) is the number of bytes comprising the data .
|
||||||
@@ -371,6 +372,11 @@ lfilter(lua_State *L) {
|
|||||||
lua_pushinteger(L, message->id);
|
lua_pushinteger(L, message->id);
|
||||||
pushstring(L, buffer, size);
|
pushstring(L, buffer, size);
|
||||||
return 4;
|
return 4;
|
||||||
|
case SKYNET_SOCKET_TYPE_WARNING:
|
||||||
|
lua_pushvalue(L, lua_upvalueindex(TYPE_WARNING));
|
||||||
|
lua_pushinteger(L, message->id);
|
||||||
|
lua_pushinteger(L, message->ud);
|
||||||
|
return 4;
|
||||||
default:
|
default:
|
||||||
// never get here
|
// never get here
|
||||||
return 1;
|
return 1;
|
||||||
@@ -442,57 +448,6 @@ lpack(lua_State *L) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
lpack_string(lua_State *L) {
|
|
||||||
uint8_t tmp[SMALLSTRING+2];
|
|
||||||
size_t len;
|
|
||||||
uint8_t *buffer;
|
|
||||||
const char * ptr = tolstring(L, &len, 1);
|
|
||||||
if (len > 0x10000) {
|
|
||||||
return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len <= SMALLSTRING) {
|
|
||||||
buffer = tmp;
|
|
||||||
} else {
|
|
||||||
buffer = lua_newuserdata(L, len + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_size(buffer, len);
|
|
||||||
memcpy(buffer+2, ptr, len);
|
|
||||||
lua_pushlstring(L, (const char *)buffer, len+2);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
lpack_padding(lua_State *L) {
|
|
||||||
uint8_t tmp[SMALLSTRING+2];
|
|
||||||
size_t content_sz;
|
|
||||||
uint8_t *buffer;
|
|
||||||
const char * ptr = tolstring(L, &content_sz, 2);
|
|
||||||
size_t cookie_sz = 0;
|
|
||||||
const char * cookie = luaL_checklstring(L,1,&cookie_sz);
|
|
||||||
size_t len = cookie_sz + content_sz;
|
|
||||||
|
|
||||||
if (len > 0x10000) {
|
|
||||||
return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len <= SMALLSTRING) {
|
|
||||||
buffer = tmp;
|
|
||||||
} else {
|
|
||||||
buffer = lua_newuserdata(L, len + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_size(buffer, len);
|
|
||||||
memcpy(buffer+2, ptr, content_sz);
|
|
||||||
memcpy(buffer+2+content_sz, cookie, cookie_sz);
|
|
||||||
lua_pushlstring(L, (const char *)buffer, len+2);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ltostring(lua_State *L) {
|
ltostring(lua_State *L) {
|
||||||
void * ptr = lua_touserdata(L, 1);
|
void * ptr = lua_touserdata(L, 1);
|
||||||
@@ -500,19 +455,8 @@ ltostring(lua_State *L) {
|
|||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
lua_pushliteral(L, "");
|
lua_pushliteral(L, "");
|
||||||
} else {
|
} else {
|
||||||
if (lua_isnumber(L, 3)) {
|
lua_pushlstring(L, (const char *)ptr, size);
|
||||||
int offset = lua_tointeger(L, 3);
|
skynet_free(ptr);
|
||||||
if (offset < 0) {
|
|
||||||
return luaL_error(L, "Invalid offset %d", offset);
|
|
||||||
}
|
|
||||||
if (offset > size) {
|
|
||||||
offset = size;
|
|
||||||
}
|
|
||||||
lua_pushlstring(L, (const char *)ptr + offset, size-offset);
|
|
||||||
} else {
|
|
||||||
lua_pushlstring(L, (const char *)ptr, size);
|
|
||||||
skynet_free(ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -523,8 +467,6 @@ luaopen_netpack(lua_State *L) {
|
|||||||
luaL_Reg l[] = {
|
luaL_Reg l[] = {
|
||||||
{ "pop", lpop },
|
{ "pop", lpop },
|
||||||
{ "pack", lpack },
|
{ "pack", lpack },
|
||||||
{ "pack_string", lpack_string },
|
|
||||||
{ "pack_padding", lpack_padding },
|
|
||||||
{ "clear", lclear },
|
{ "clear", lclear },
|
||||||
{ "tostring", ltostring },
|
{ "tostring", ltostring },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
@@ -537,8 +479,9 @@ luaopen_netpack(lua_State *L) {
|
|||||||
lua_pushliteral(L, "error");
|
lua_pushliteral(L, "error");
|
||||||
lua_pushliteral(L, "open");
|
lua_pushliteral(L, "open");
|
||||||
lua_pushliteral(L, "close");
|
lua_pushliteral(L, "close");
|
||||||
|
lua_pushliteral(L, "warning");
|
||||||
|
|
||||||
lua_pushcclosure(L, lfilter, 5);
|
lua_pushcclosure(L, lfilter, 6);
|
||||||
lua_setfield(L, -2, "filter");
|
lua_setfield(L, -2, "filter");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -254,14 +254,41 @@ wb_table_hash(lua_State *L, struct write_block * wb, int index, int depth, int a
|
|||||||
wb_nil(wb);
|
wb_nil(wb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wb_table_metapairs(lua_State *L, struct write_block *wb, int index, int depth) {
|
||||||
|
uint8_t n = COMBINE_TYPE(TYPE_TABLE, 0);
|
||||||
|
wb_push(wb, &n, 1);
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
lua_call(L, 1, 3);
|
||||||
|
for(;;) {
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_copy(L, -5, -3);
|
||||||
|
lua_call(L, 2, 2);
|
||||||
|
int type = lua_type(L, -2);
|
||||||
|
if (type == LUA_TNIL) {
|
||||||
|
lua_pop(L, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pack_one(L, wb, -2, depth);
|
||||||
|
pack_one(L, wb, -1, depth);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
wb_nil(wb);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wb_table(lua_State *L, struct write_block *wb, int index, int depth) {
|
wb_table(lua_State *L, struct write_block *wb, int index, int depth) {
|
||||||
luaL_checkstack(L, LUA_MINSTACK, NULL);
|
luaL_checkstack(L, LUA_MINSTACK, NULL);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = lua_gettop(L) + index + 1;
|
index = lua_gettop(L) + index + 1;
|
||||||
}
|
}
|
||||||
int array_size = wb_table_array(L, wb, index, depth);
|
if (luaL_getmetafield(L, index, "__pairs") != LUA_TNIL) {
|
||||||
wb_table_hash(L, wb, index, depth, array_size);
|
wb_table_metapairs(L, wb, index, depth);
|
||||||
|
} else {
|
||||||
|
int array_size = wb_table_array(L, wb, index, depth);
|
||||||
|
wb_table_hash(L, wb, index, depth, array_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
#define KEYTYPE_INTEGER 0
|
#define KEYTYPE_INTEGER 0
|
||||||
#define KEYTYPE_STRING 1
|
#define KEYTYPE_STRING 1
|
||||||
@@ -376,6 +377,7 @@ pconv(lua_State *L) {
|
|||||||
static void
|
static void
|
||||||
convert_stringmap(struct context *ctx, struct table *tbl) {
|
convert_stringmap(struct context *ctx, struct table *tbl) {
|
||||||
lua_State *L = ctx->L;
|
lua_State *L = ctx->L;
|
||||||
|
lua_checkstack(L, ctx->string_index + LUA_MINSTACK);
|
||||||
lua_settop(L, ctx->string_index + 1);
|
lua_settop(L, ctx->string_index + 1);
|
||||||
lua_pushvalue(L, 1);
|
lua_pushvalue(L, 1);
|
||||||
struct state * s = lua_newuserdata(L, sizeof(*s));
|
struct state * s = lua_newuserdata(L, sizeof(*s));
|
||||||
@@ -662,7 +664,7 @@ releaseobj(lua_State *L) {
|
|||||||
struct ctrl *c = lua_touserdata(L, 1);
|
struct ctrl *c = lua_touserdata(L, 1);
|
||||||
struct table *tbl = c->root;
|
struct table *tbl = c->root;
|
||||||
struct state *s = lua_touserdata(tbl->L, 1);
|
struct state *s = lua_touserdata(tbl->L, 1);
|
||||||
__sync_fetch_and_sub(&s->ref, 1);
|
ATOM_DEC(&s->ref);
|
||||||
c->root = NULL;
|
c->root = NULL;
|
||||||
c->update = NULL;
|
c->update = NULL;
|
||||||
|
|
||||||
@@ -673,7 +675,7 @@ static int
|
|||||||
lboxconf(lua_State *L) {
|
lboxconf(lua_State *L) {
|
||||||
struct table * tbl = get_table(L,1);
|
struct table * tbl = get_table(L,1);
|
||||||
struct state * s = lua_touserdata(tbl->L, 1);
|
struct state * s = lua_touserdata(tbl->L, 1);
|
||||||
__sync_fetch_and_add(&s->ref, 1);
|
ATOM_INC(&s->ref);
|
||||||
|
|
||||||
struct ctrl * c = lua_newuserdata(L, sizeof(*c));
|
struct ctrl * c = lua_newuserdata(L, sizeof(*c));
|
||||||
c->root = tbl;
|
c->root = tbl;
|
||||||
@@ -718,7 +720,7 @@ static int
|
|||||||
lincref(lua_State *L) {
|
lincref(lua_State *L) {
|
||||||
struct table *tbl = get_table(L,1);
|
struct table *tbl = get_table(L,1);
|
||||||
struct state * s = lua_touserdata(tbl->L, 1);
|
struct state * s = lua_touserdata(tbl->L, 1);
|
||||||
int ref = __sync_add_and_fetch(&s->ref, 1);
|
int ref = ATOM_INC(&s->ref);
|
||||||
lua_pushinteger(L , ref);
|
lua_pushinteger(L , ref);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -728,7 +730,7 @@ static int
|
|||||||
ldecref(lua_State *L) {
|
ldecref(lua_State *L) {
|
||||||
struct table *tbl = get_table(L,1);
|
struct table *tbl = get_table(L,1);
|
||||||
struct state * s = lua_touserdata(tbl->L, 1);
|
struct state * s = lua_touserdata(tbl->L, 1);
|
||||||
int ref = __sync_sub_and_fetch(&s->ref, 1);
|
int ref = ATOM_DEC(&s->ref);
|
||||||
lua_pushinteger(L , ref);
|
lua_pushinteger(L , ref);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -118,6 +118,28 @@ _command(lua_State *L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_intcommand(lua_State *L) {
|
||||||
|
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
|
||||||
|
const char * cmd = luaL_checkstring(L,1);
|
||||||
|
const char * result;
|
||||||
|
const char * parm = NULL;
|
||||||
|
char tmp[64]; // for integer parm
|
||||||
|
if (lua_gettop(L) == 2) {
|
||||||
|
int32_t n = (int32_t)luaL_checkinteger(L,2);
|
||||||
|
sprintf(tmp, "%d", n);
|
||||||
|
parm = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = skynet_command(context, cmd, parm);
|
||||||
|
if (result) {
|
||||||
|
lua_Integer r = strtoll(result, NULL, 0);
|
||||||
|
lua_pushinteger(L, r);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_genid(lua_State *L) {
|
_genid(lua_State *L) {
|
||||||
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
|
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@@ -150,6 +172,9 @@ _send(lua_State *L) {
|
|||||||
uint32_t dest = (uint32_t)lua_tointeger(L, 1);
|
uint32_t dest = (uint32_t)lua_tointeger(L, 1);
|
||||||
const char * dest_string = NULL;
|
const char * dest_string = NULL;
|
||||||
if (dest == 0) {
|
if (dest == 0) {
|
||||||
|
if (lua_type(L,1) == LUA_TNUMBER) {
|
||||||
|
return luaL_error(L, "Invalid service address 0");
|
||||||
|
}
|
||||||
dest_string = get_dest_string(L, 1);
|
dest_string = get_dest_string(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +335,7 @@ luaopen_skynet_core(lua_State *L) {
|
|||||||
{ "genid", _genid },
|
{ "genid", _genid },
|
||||||
{ "redirect", _redirect },
|
{ "redirect", _redirect },
|
||||||
{ "command" , _command },
|
{ "command" , _command },
|
||||||
|
{ "intcommand", _intcommand },
|
||||||
{ "error", _error },
|
{ "error", _error },
|
||||||
{ "tostring", _tostring },
|
{ "tostring", _tostring },
|
||||||
{ "harbor", _harbor },
|
{ "harbor", _harbor },
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "rwlock.h"
|
#include "rwlock.h"
|
||||||
#include "skynet_malloc.h"
|
#include "skynet_malloc.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
struct stm_object {
|
struct stm_object {
|
||||||
struct rwlock lock;
|
struct rwlock lock;
|
||||||
@@ -45,7 +46,7 @@ static void
|
|||||||
stm_releasecopy(struct stm_copy *copy) {
|
stm_releasecopy(struct stm_copy *copy) {
|
||||||
if (copy == NULL)
|
if (copy == NULL)
|
||||||
return;
|
return;
|
||||||
if (__sync_sub_and_fetch(©->reference, 1) == 0) {
|
if (ATOM_DEC(©->reference) == 0) {
|
||||||
skynet_free(copy->msg);
|
skynet_free(copy->msg);
|
||||||
skynet_free(copy);
|
skynet_free(copy);
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ stm_release(struct stm_object *obj) {
|
|||||||
static void
|
static void
|
||||||
stm_releasereader(struct stm_object *obj) {
|
stm_releasereader(struct stm_object *obj) {
|
||||||
rwlock_rlock(&obj->lock);
|
rwlock_rlock(&obj->lock);
|
||||||
if (__sync_sub_and_fetch(&obj->reference,1) == 0) {
|
if (ATOM_DEC(&obj->reference) == 0) {
|
||||||
// last reader, no writer. so no need to unlock
|
// last reader, no writer. so no need to unlock
|
||||||
assert(obj->copy == NULL);
|
assert(obj->copy == NULL);
|
||||||
skynet_free(obj);
|
skynet_free(obj);
|
||||||
@@ -82,7 +83,7 @@ stm_releasereader(struct stm_object *obj) {
|
|||||||
static void
|
static void
|
||||||
stm_grab(struct stm_object *obj) {
|
stm_grab(struct stm_object *obj) {
|
||||||
rwlock_rlock(&obj->lock);
|
rwlock_rlock(&obj->lock);
|
||||||
int ref = __sync_fetch_and_add(&obj->reference,1);
|
int ref = ATOM_FINC(&obj->reference);
|
||||||
rwlock_runlock(&obj->lock);
|
rwlock_runlock(&obj->lock);
|
||||||
assert(ref > 0);
|
assert(ref > 0);
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ stm_copy(struct stm_object *obj) {
|
|||||||
rwlock_rlock(&obj->lock);
|
rwlock_rlock(&obj->lock);
|
||||||
struct stm_copy * ret = obj->copy;
|
struct stm_copy * ret = obj->copy;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
int ref = __sync_fetch_and_add(&ret->reference,1);
|
int ref = ATOM_FINC(&ret->reference);
|
||||||
assert(ref > 0);
|
assert(ref > 0);
|
||||||
}
|
}
|
||||||
rwlock_runlock(&obj->lock);
|
rwlock_runlock(&obj->lock);
|
||||||
|
|||||||
@@ -487,10 +487,10 @@ lunpack(lua_State *L) {
|
|||||||
return luaL_error(L, "Invalid unpack stream");
|
return luaL_error(L, "Invalid unpack stream");
|
||||||
if (r > osz) {
|
if (r > osz) {
|
||||||
output = expand_buffer(L, osz, r);
|
output = expand_buffer(L, osz, r);
|
||||||
|
r = sproto_unpack(buffer, sz, output, r);
|
||||||
|
if (r < 0)
|
||||||
|
return luaL_error(L, "Invalid unpack stream");
|
||||||
}
|
}
|
||||||
r = sproto_unpack(buffer, sz, output, r);
|
|
||||||
if (r < 0)
|
|
||||||
return luaL_error(L, "Invalid unpack stream");
|
|
||||||
lua_pushlstring(L, output, r);
|
lua_pushlstring(L, output, r);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static void *
|
|||||||
pool_alloc(struct pool *p, size_t sz) {
|
pool_alloc(struct pool *p, size_t sz) {
|
||||||
// align by 8
|
// align by 8
|
||||||
sz = (sz + 7) & ~7;
|
sz = (sz + 7) & ~7;
|
||||||
if (sz > CHUNK_SIZE) {
|
if (sz >= CHUNK_SIZE) {
|
||||||
return pool_newchunk(p, sz);
|
return pool_newchunk(p, sz);
|
||||||
}
|
}
|
||||||
if (p->current == NULL) {
|
if (p->current == NULL) {
|
||||||
@@ -97,7 +97,7 @@ pool_alloc(struct pool *p, size_t sz) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sz > p->current_used) {
|
if (sz >= p->current_used) {
|
||||||
return pool_newchunk(p, sz);
|
return pool_newchunk(p, sz);
|
||||||
} else {
|
} else {
|
||||||
void * ret = pool_newchunk(p, CHUNK_SIZE);
|
void * ret = pool_newchunk(p, CHUNK_SIZE);
|
||||||
@@ -152,7 +152,7 @@ struct_field(const uint8_t * stream, size_t sz) {
|
|||||||
sz -= header;
|
sz -= header;
|
||||||
stream += header;
|
stream += header;
|
||||||
for (i=0;i<fn;i++) {
|
for (i=0;i<fn;i++) {
|
||||||
int value= toword(field + i * SIZEOF_FIELD + SIZEOF_HEADER);
|
int value= toword(field + i * SIZEOF_FIELD);
|
||||||
uint32_t dsz;
|
uint32_t dsz;
|
||||||
if (value != 0)
|
if (value != 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -305,7 +305,7 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
|
|||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
tag = f->tag;
|
tag = f->tag;
|
||||||
if (tag < last)
|
if (tag <= last)
|
||||||
return NULL; // tag must in ascending order
|
return NULL; // tag must in ascending order
|
||||||
if (tag > last+1) {
|
if (tag > last+1) {
|
||||||
++maxn;
|
++maxn;
|
||||||
@@ -394,7 +394,7 @@ create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
|
|||||||
const uint8_t * protocoldata = NULL;
|
const uint8_t * protocoldata = NULL;
|
||||||
int fn = struct_field(stream, sz);
|
int fn = struct_field(stream, sz);
|
||||||
int i;
|
int i;
|
||||||
if (fn < 0)
|
if (fn < 0 || fn > 2)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
stream += SIZEOF_HEADER;
|
stream += SIZEOF_HEADER;
|
||||||
|
|||||||
@@ -33,6 +33,16 @@ function cluster.snax(node, name, address)
|
|||||||
return snax.bind(handle, name)
|
return snax.bind(handle, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cluster.register(name, addr)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(addr == nil or type(addr) == "number")
|
||||||
|
return skynet.call(clusterd, "lua", "register", name, addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function cluster.query(node, name)
|
||||||
|
return skynet.call(clusterd, "lua", "req", node, 0, skynet.pack(name))
|
||||||
|
end
|
||||||
|
|
||||||
skynet.init(function()
|
skynet.init(function()
|
||||||
clusterd = skynet.uniqueservice("clusterd")
|
clusterd = skynet.uniqueservice("clusterd")
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ local dispatch = setmetatable({} , {__mode = "kv" })
|
|||||||
local chan = {}
|
local chan = {}
|
||||||
local chan_meta = {
|
local chan_meta = {
|
||||||
__index = chan,
|
__index = chan,
|
||||||
__gc = unsubscribe,
|
__gc = function(self)
|
||||||
|
self:unsubscribe()
|
||||||
|
end,
|
||||||
__tostring = function (self)
|
__tostring = function (self)
|
||||||
return string.format("[Multicast:%x]",self.channel)
|
return string.format("[Multicast:%x]",self.channel)
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -386,7 +386,8 @@ end
|
|||||||
|
|
||||||
local function _recv_decode_packet_resp(self)
|
local function _recv_decode_packet_resp(self)
|
||||||
return function(sock)
|
return function(sock)
|
||||||
return true, _recv_packet(self,sock)
|
-- don't return more than 2 results
|
||||||
|
return true, (_recv_packet(self,sock))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -248,18 +248,16 @@ function suspend(co, result, command, param, size)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.timeout(ti, func)
|
function skynet.timeout(ti, func)
|
||||||
local session = c.command("TIMEOUT",tostring(ti))
|
local session = c.intcommand("TIMEOUT",ti)
|
||||||
assert(session)
|
assert(session)
|
||||||
session = tonumber(session)
|
|
||||||
local co = co_create(func)
|
local co = co_create(func)
|
||||||
assert(session_id_coroutine[session] == nil)
|
assert(session_id_coroutine[session] == nil)
|
||||||
session_id_coroutine[session] = co
|
session_id_coroutine[session] = co
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.sleep(ti)
|
function skynet.sleep(ti)
|
||||||
local session = c.command("TIMEOUT",tostring(ti))
|
local session = c.intcommand("TIMEOUT",ti)
|
||||||
assert(session)
|
assert(session)
|
||||||
session = tonumber(session)
|
|
||||||
local succ, ret = coroutine_yield("SLEEP", session)
|
local succ, ret = coroutine_yield("SLEEP", session)
|
||||||
sleep_session[coroutine.running()] = nil
|
sleep_session[coroutine.running()] = nil
|
||||||
if succ then
|
if succ then
|
||||||
@@ -273,7 +271,7 @@ function skynet.sleep(ti)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.yield()
|
function skynet.yield()
|
||||||
return skynet.sleep("0")
|
return skynet.sleep(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.wait()
|
function skynet.wait()
|
||||||
@@ -301,11 +299,11 @@ function skynet.localname(name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.now()
|
function skynet.now()
|
||||||
return tonumber(c.command("NOW"))
|
return c.intcommand("NOW")
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.starttime()
|
function skynet.starttime()
|
||||||
return tonumber(c.command("STARTTIME"))
|
return c.intcommand("STARTTIME")
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.time()
|
function skynet.time()
|
||||||
@@ -415,9 +413,14 @@ function skynet.wakeup(co)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.dispatch(typename, func)
|
function skynet.dispatch(typename, func)
|
||||||
local p = assert(proto[typename],tostring(typename))
|
local p = proto[typename]
|
||||||
assert(p.dispatch == nil, tostring(typename))
|
if func then
|
||||||
p.dispatch = func
|
local ret = p.dispatch
|
||||||
|
p.dispatch = func
|
||||||
|
return ret
|
||||||
|
else
|
||||||
|
return p and p.dispatch
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function unknown_request(session, address, msg, sz, prototype)
|
local function unknown_request(session, address, msg, sz, prototype)
|
||||||
@@ -466,7 +469,15 @@ local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
|
|||||||
suspend(co, coroutine.resume(co, true, msg, sz))
|
suspend(co, coroutine.resume(co, true, msg, sz))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local p = assert(proto[prototype], prototype)
|
local p = proto[prototype]
|
||||||
|
if p == nil then
|
||||||
|
if session ~= 0 then
|
||||||
|
c.send(source, skynet.PTYPE_ERROR, session, "")
|
||||||
|
else
|
||||||
|
unknown_request(session, source, msg, sz, prototype)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
local f = p.dispatch
|
local f = p.dispatch
|
||||||
if f then
|
if f then
|
||||||
local ref = watching_service[source]
|
local ref = watching_service[source]
|
||||||
@@ -630,7 +641,7 @@ function skynet.endless()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.mqlen()
|
function skynet.mqlen()
|
||||||
return tonumber(c.command "MQLEN")
|
return c.intcommand "MQLEN"
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.task(ret)
|
function skynet.task(ret)
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ function skynet.info_func(func)
|
|||||||
internal_info_func = func
|
internal_info_func = func
|
||||||
end
|
end
|
||||||
|
|
||||||
local dbgcmd = {}
|
local dbgcmd
|
||||||
|
|
||||||
|
local function init_dbgcmd()
|
||||||
|
dbgcmd = {}
|
||||||
|
|
||||||
function dbgcmd.MEM()
|
function dbgcmd.MEM()
|
||||||
local kb, bytes = collectgarbage "count"
|
local kb, bytes = collectgarbage "count"
|
||||||
@@ -63,8 +66,15 @@ function dbgcmd.REMOTEDEBUG(...)
|
|||||||
remotedebug.start(export, ...)
|
remotedebug.start(export, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dbgcmd.SUPPORT(pname)
|
||||||
|
return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
|
||||||
|
end
|
||||||
|
|
||||||
|
return dbgcmd
|
||||||
|
end -- function init_dbgcmd
|
||||||
|
|
||||||
local function _debug_dispatch(session, address, cmd, ...)
|
local function _debug_dispatch(session, address, cmd, ...)
|
||||||
local f = dbgcmd[cmd]
|
local f = (dbgcmd or init_dbgcmd())[cmd] -- lazy init dbgcmd
|
||||||
assert(f, cmd)
|
assert(f, cmd)
|
||||||
f(...)
|
f(...)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -114,6 +114,12 @@ function gateserver.start(handler)
|
|||||||
close_fd(fd)
|
close_fd(fd)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MSG.warning(fd, size)
|
||||||
|
if handler.warning then
|
||||||
|
handler.warning(fd, size)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
skynet.register_protocol {
|
skynet.register_protocol {
|
||||||
name = "socket",
|
name = "socket",
|
||||||
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
|
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ local function collect_all_uv(funcs)
|
|||||||
collect_uv(v[4], global, envid(v[4]))
|
collect_uv(v[4], global, envid(v[4]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not global["_ENV"] then
|
||||||
|
global["_ENV"] = {func = collect_uv, index = 1}
|
||||||
|
end
|
||||||
return global
|
return global
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ Config for server.start:
|
|||||||
conf.login_handler(uid, secret) -> subid : the function when a new user login, alloc a subid for it. (may call by login server)
|
conf.login_handler(uid, secret) -> subid : the function when a new user login, alloc a subid for it. (may call by login server)
|
||||||
conf.logout_handler(uid, subid) : the functon when a user logout. (may call by agent)
|
conf.logout_handler(uid, subid) : the functon when a user logout. (may call by agent)
|
||||||
conf.kick_handler(uid, subid) : the functon when a user logout. (may call by login server)
|
conf.kick_handler(uid, subid) : the functon when a user logout. (may call by login server)
|
||||||
conf.request_handler(username, session, msg, sz) : the function when recv a new request.
|
conf.request_handler(username, session, msg) : the function when recv a new request.
|
||||||
conf.register_handler(servername) : call when gate open
|
conf.register_handler(servername) : call when gate open
|
||||||
conf.disconnect_handler(username) : call when a connection disconnect (afk)
|
conf.disconnect_handler(username) : call when a connection disconnect (afk)
|
||||||
]]
|
]]
|
||||||
@@ -234,10 +234,10 @@ function server.start(conf)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function do_request(fd, msg, sz)
|
local function do_request(fd, message)
|
||||||
local u = assert(connection[fd], "invalid fd")
|
local u = assert(connection[fd], "invalid fd")
|
||||||
local msg_sz = sz - 4
|
local session = string.unpack(">I4", message, -4)
|
||||||
local session = netpack.tostring(msg, sz, msg_sz)
|
message = message:sub(1,-5)
|
||||||
local p = u.response[session]
|
local p = u.response[session]
|
||||||
if p then
|
if p then
|
||||||
-- session can be reuse in the same connection
|
-- session can be reuse in the same connection
|
||||||
@@ -256,21 +256,20 @@ function server.start(conf)
|
|||||||
if p == nil then
|
if p == nil then
|
||||||
p = { fd }
|
p = { fd }
|
||||||
u.response[session] = p
|
u.response[session] = p
|
||||||
local ok, result = pcall(conf.request_handler, u.username, msg, msg_sz)
|
local ok, result = pcall(conf.request_handler, u.username, message)
|
||||||
result = result or ""
|
|
||||||
-- NOTICE: YIELD here, socket may close.
|
-- NOTICE: YIELD here, socket may close.
|
||||||
|
result = result or ""
|
||||||
if not ok then
|
if not ok then
|
||||||
skynet.error(result)
|
skynet.error(result)
|
||||||
result = "\0" .. session
|
result = string.pack(">BI4", 0, session)
|
||||||
else
|
else
|
||||||
result = result .. '\1' .. session
|
result = result .. string.pack(">BI4", 1, session)
|
||||||
end
|
end
|
||||||
|
|
||||||
p[2] = netpack.pack_string(result)
|
p[2] = string.pack(">s2",result)
|
||||||
p[3] = u.version
|
p[3] = u.version
|
||||||
p[4] = u.index
|
p[4] = u.index
|
||||||
else
|
else
|
||||||
netpack.tostring(msg, sz) -- request before, so free msg
|
|
||||||
-- update version/index, change return fd.
|
-- update version/index, change return fd.
|
||||||
-- resend response.
|
-- resend response.
|
||||||
p[1] = fd
|
p[1] = fd
|
||||||
@@ -292,10 +291,11 @@ function server.start(conf)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function request(fd, msg, sz)
|
local function request(fd, msg, sz)
|
||||||
local ok, err = pcall(do_request, fd, msg, sz)
|
local message = netpack.tostring(msg, sz)
|
||||||
|
local ok, err = pcall(do_request, fd, message)
|
||||||
-- not atomic, may yield
|
-- not atomic, may yield
|
||||||
if not ok then
|
if not ok then
|
||||||
skynet.error(string.format("Invalid package %s : %s", err, netpack.tostring(msg, sz)))
|
skynet.error(string.format("Invalid package %s : %s", err, message))
|
||||||
if connection[fd] then
|
if connection[fd] then
|
||||||
gateserver.closeclient(fd)
|
gateserver.closeclient(fd)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -133,6 +133,25 @@ socket_message[6] = function(id, size, data, address)
|
|||||||
s.callback(str, address)
|
s.callback(str, address)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function default_warning(id, size)
|
||||||
|
local s = socket_pool[id]
|
||||||
|
local last = s.warningsize or 0
|
||||||
|
if last + 64 < size then -- if size increase 64K
|
||||||
|
s.warningsize = size
|
||||||
|
skynet.error(string.format("WARNING: %d K bytes need to send out (fd = %d)", size, id))
|
||||||
|
end
|
||||||
|
s.warningsize = size
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SKYNET_SOCKET_TYPE_WARNING
|
||||||
|
socket_message[7] = function(id, size)
|
||||||
|
local s = socket_pool[id]
|
||||||
|
if s then
|
||||||
|
local warning = s.warning or default_warning
|
||||||
|
warning(id, size)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
skynet.register_protocol {
|
skynet.register_protocol {
|
||||||
name = "socket",
|
name = "socket",
|
||||||
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
|
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
|
||||||
@@ -404,4 +423,10 @@ end
|
|||||||
socket.sendto = assert(driver.udp_send)
|
socket.sendto = assert(driver.udp_send)
|
||||||
socket.udp_address = assert(driver.udp_address)
|
socket.udp_address = assert(driver.udp_address)
|
||||||
|
|
||||||
|
function socket.warning(id, callback)
|
||||||
|
local obj = socket_pool[id]
|
||||||
|
assert(obj)
|
||||||
|
obj.warning = callback
|
||||||
|
end
|
||||||
|
|
||||||
return socket
|
return socket
|
||||||
|
|||||||
@@ -81,15 +81,27 @@ local function dispatch_by_session(self)
|
|||||||
local response = self.__response
|
local response = self.__response
|
||||||
-- response() return session
|
-- response() return session
|
||||||
while self.__sock do
|
while self.__sock do
|
||||||
local ok , session, result_ok, result_data = pcall(response, self.__sock)
|
local ok , session, result_ok, result_data, padding = pcall(response, self.__sock)
|
||||||
if ok and session then
|
if ok and session then
|
||||||
local co = self.__thread[session]
|
local co = self.__thread[session]
|
||||||
self.__thread[session] = nil
|
|
||||||
if co then
|
if co then
|
||||||
self.__result[co] = result_ok
|
if padding and result_ok then
|
||||||
self.__result_data[co] = result_data
|
-- If padding is true, append result_data to a table (self.__result_data[co])
|
||||||
skynet.wakeup(co)
|
local result = self.__result_data[co] or {}
|
||||||
|
self.__result_data[co] = result
|
||||||
|
table.insert(result, result_data)
|
||||||
|
else
|
||||||
|
self.__thread[session] = nil
|
||||||
|
self.__result[co] = result_ok
|
||||||
|
if result_ok and self.__result_data[co] then
|
||||||
|
table.insert(self.__result_data[co], result_data)
|
||||||
|
else
|
||||||
|
self.__result_data[co] = result_data
|
||||||
|
end
|
||||||
|
skynet.wakeup(co)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
|
self.__thread[session] = nil
|
||||||
skynet.error("socket: unknown session :", session)
|
skynet.error("socket: unknown session :", session)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -127,11 +139,23 @@ local function dispatch_by_order(self)
|
|||||||
wakeup_all(self)
|
wakeup_all(self)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local ok, result_ok, result_data = pcall(func, self.__sock)
|
local ok, result_ok, result_data, padding = pcall(func, self.__sock)
|
||||||
if ok then
|
if ok then
|
||||||
self.__result[co] = result_ok
|
if padding and result_ok then
|
||||||
self.__result_data[co] = result_data
|
-- if padding is true, wait for next result_data
|
||||||
skynet.wakeup(co)
|
-- self.__result_data[co] is a table
|
||||||
|
local result = self.__result_data[co] or {}
|
||||||
|
self.__result_data[co] = result
|
||||||
|
table.insert(result, result_data)
|
||||||
|
else
|
||||||
|
self.__result[co] = result_ok
|
||||||
|
if result_ok and self.__result_data[co] then
|
||||||
|
table.insert(self.__result_data[co], result_data)
|
||||||
|
else
|
||||||
|
self.__result_data[co] = result_data
|
||||||
|
end
|
||||||
|
skynet.wakeup(co)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
close_channel_socket(self)
|
close_channel_socket(self)
|
||||||
local errmsg
|
local errmsg
|
||||||
@@ -314,13 +338,27 @@ local function wait_for_response(self, response)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function channel:request(request, response)
|
local socket_write = socket.write
|
||||||
assert(block_connect(self, true)) -- connect once
|
local socket_lwrite = socket.lwrite
|
||||||
|
|
||||||
if not socket.write(self.__sock[1], request) then
|
function channel:request(request, response, padding)
|
||||||
close_channel_socket(self)
|
assert(block_connect(self, true)) -- connect once
|
||||||
wakeup_all(self)
|
local fd = self.__sock[1]
|
||||||
error(socket_error)
|
|
||||||
|
if padding then
|
||||||
|
-- padding may be a table, to support multi part request
|
||||||
|
-- multi part request use low priority socket write
|
||||||
|
-- socket_lwrite returns nothing
|
||||||
|
socket_lwrite(fd , request)
|
||||||
|
for _,v in ipairs(padding) do
|
||||||
|
socket_lwrite(fd, v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if not socket_write(fd , request) then
|
||||||
|
close_channel_socket(self)
|
||||||
|
wakeup_all(self)
|
||||||
|
error(socket_error)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if response == nil then
|
if response == nil then
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ end
|
|||||||
|
|
||||||
local typedef = P {
|
local typedef = P {
|
||||||
"ALL",
|
"ALL",
|
||||||
FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^0 * typename * mainkey^0)),
|
FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^-1 * typename * mainkey^0)),
|
||||||
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
|
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
|
||||||
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
|
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
|
||||||
SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")),
|
SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")),
|
||||||
|
|||||||
@@ -262,6 +262,9 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes
|
|||||||
skynet_socket_start(ctx, message->ud);
|
skynet_socket_start(ctx, message->ud);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SKYNET_SOCKET_TYPE_WARNING:
|
||||||
|
skynet_error(ctx, "fd (%d) send buffer (%d)K", message->id, message->ud);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
#include "skynet_harbor.h"
|
#include "skynet_harbor.h"
|
||||||
#include "skynet_socket.h"
|
#include "skynet_socket.h"
|
||||||
|
#include "skynet_handle.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
harbor listen the PTYPE_HARBOR (in text)
|
harbor listen the PTYPE_HARBOR (in text)
|
||||||
@@ -323,9 +324,13 @@ forward_local_messsage(struct harbor *h, void *msg, int sz) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
send_remote(struct skynet_context * ctx, int fd, const char * buffer, size_t sz, struct remote_message_header * cookie) {
|
send_remote(struct skynet_context * ctx, int fd, const char * buffer, size_t sz, struct remote_message_header * cookie) {
|
||||||
uint32_t sz_header = sz+sizeof(*cookie);
|
size_t sz_header = sz+sizeof(*cookie);
|
||||||
|
if (sz_header > UINT32_MAX) {
|
||||||
|
skynet_error(ctx, "remote message from :%08x to :%08x is too large.", cookie->source, cookie->destination);
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint8_t * sendbuf = skynet_malloc(sz_header+4);
|
uint8_t * sendbuf = skynet_malloc(sz_header+4);
|
||||||
to_bigendian(sendbuf, sz_header);
|
to_bigendian(sendbuf, (uint32_t)sz_header);
|
||||||
memcpy(sendbuf+4, buffer, sz);
|
memcpy(sendbuf+4, buffer, sz);
|
||||||
header_to_message(cookie, sendbuf+4+sz);
|
header_to_message(cookie, sendbuf+4+sz);
|
||||||
|
|
||||||
@@ -657,6 +662,13 @@ mainloop(struct skynet_context * context, void * ud, int type, int session, uint
|
|||||||
case SKYNET_SOCKET_TYPE_CONNECT:
|
case SKYNET_SOCKET_TYPE_CONNECT:
|
||||||
// fd forward to this service
|
// fd forward to this service
|
||||||
break;
|
break;
|
||||||
|
case SKYNET_SOCKET_TYPE_WARNING: {
|
||||||
|
int id = harbor_id(h, message->id);
|
||||||
|
if (id) {
|
||||||
|
skynet_error(context, "message havn't send to Harbor (%d) reach %d K", id, message->ud);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
skynet_error(context, "recv invalid socket message type %d", type);
|
skynet_error(context, "recv invalid socket message type %d", type);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ require "skynet.manager" -- import skynet.launch, ...
|
|||||||
local globalname = {}
|
local globalname = {}
|
||||||
local queryname = {}
|
local queryname = {}
|
||||||
local harbor = {}
|
local harbor = {}
|
||||||
|
local harbor_service
|
||||||
|
|
||||||
skynet.register_protocol {
|
skynet.register_protocol {
|
||||||
name = "harbor",
|
name = "harbor",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ local command = {}
|
|||||||
local function read_response(sock)
|
local function read_response(sock)
|
||||||
local sz = socket.header(sock:read(2))
|
local sz = socket.header(sock:read(2))
|
||||||
local msg = sock:read(sz)
|
local msg = sock:read(sz)
|
||||||
return cluster.unpackresponse(msg) -- session, ok, data
|
return cluster.unpackresponse(msg) -- session, ok, data, padding
|
||||||
end
|
end
|
||||||
|
|
||||||
local function open_channel(t, key)
|
local function open_channel(t, key)
|
||||||
@@ -24,7 +24,6 @@ local function open_channel(t, key)
|
|||||||
}
|
}
|
||||||
assert(c:connect(true))
|
assert(c:connect(true))
|
||||||
t[key] = c
|
t[key] = c
|
||||||
node_session[key] = 1
|
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -63,19 +62,25 @@ function command.listen(source, addr, port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function send_request(source, node, addr, msg, sz)
|
local function send_request(source, node, addr, msg, sz)
|
||||||
local request
|
local session = node_session[node] or 1
|
||||||
local c = node_channel[node]
|
|
||||||
local session = node_session[node]
|
|
||||||
-- msg is a local pointer, cluster.packrequest will free it
|
-- msg is a local pointer, cluster.packrequest will free it
|
||||||
request, node_session[node] = cluster.packrequest(addr, session , msg, sz)
|
local request, new_session, padding = cluster.packrequest(addr, session, msg, sz)
|
||||||
|
node_session[node] = new_session
|
||||||
|
|
||||||
return c:request(request, session)
|
-- node_channel[node] may yield or throw error
|
||||||
|
local c = node_channel[node]
|
||||||
|
|
||||||
|
return c:request(request, session, padding)
|
||||||
end
|
end
|
||||||
|
|
||||||
function command.req(...)
|
function command.req(...)
|
||||||
local ok, msg, sz = pcall(send_request, ...)
|
local ok, msg, sz = pcall(send_request, ...)
|
||||||
if ok then
|
if ok then
|
||||||
skynet.ret(msg, sz)
|
if type(msg) == "table" then
|
||||||
|
skynet.ret(cluster.concat(msg))
|
||||||
|
else
|
||||||
|
skynet.ret(msg)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
skynet.error(msg)
|
skynet.error(msg)
|
||||||
skynet.response()(false)
|
skynet.response()(false)
|
||||||
@@ -92,23 +97,78 @@ function command.proxy(source, node, name)
|
|||||||
skynet.ret(skynet.pack(proxy[fullname]))
|
skynet.ret(skynet.pack(proxy[fullname]))
|
||||||
end
|
end
|
||||||
|
|
||||||
local request_fd = {}
|
local register_name = {}
|
||||||
|
|
||||||
|
function command.register(source, name, addr)
|
||||||
|
assert(register_name[name] == nil)
|
||||||
|
addr = addr or source
|
||||||
|
local old_name = register_name[addr]
|
||||||
|
if old_name then
|
||||||
|
register_name[old_name] = nil
|
||||||
|
end
|
||||||
|
register_name[addr] = name
|
||||||
|
register_name[name] = addr
|
||||||
|
skynet.ret(nil)
|
||||||
|
skynet.error(string.format("Register [%s] :%08x", name, addr))
|
||||||
|
end
|
||||||
|
|
||||||
|
local large_request = {}
|
||||||
|
|
||||||
function command.socket(source, subcmd, fd, msg)
|
function command.socket(source, subcmd, fd, msg)
|
||||||
if subcmd == "data" then
|
if subcmd == "data" then
|
||||||
local addr, session, msg = cluster.unpackrequest(msg)
|
local sz
|
||||||
local ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg)
|
local addr, session, msg, padding = cluster.unpackrequest(msg)
|
||||||
local response
|
if padding then
|
||||||
|
local req = large_request[session] or { addr = addr }
|
||||||
|
large_request[session] = req
|
||||||
|
table.insert(req, msg)
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local req = large_request[session]
|
||||||
|
if req then
|
||||||
|
large_request[session] = nil
|
||||||
|
table.insert(req, msg)
|
||||||
|
msg,sz = cluster.concat(req)
|
||||||
|
addr = req.addr
|
||||||
|
end
|
||||||
|
if not msg then
|
||||||
|
local response = cluster.packresponse(session, false, "Invalid large req")
|
||||||
|
socket.write(fd, response)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ok, response
|
||||||
|
if addr == 0 then
|
||||||
|
local name = skynet.unpack(msg, sz)
|
||||||
|
local addr = register_name[name]
|
||||||
|
if addr then
|
||||||
|
ok = true
|
||||||
|
msg, sz = skynet.pack(addr)
|
||||||
|
else
|
||||||
|
ok = false
|
||||||
|
msg = "name not found"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ok , msg, sz = pcall(skynet.rawcall, addr, "lua", msg, sz)
|
||||||
|
end
|
||||||
if ok then
|
if ok then
|
||||||
response = cluster.packresponse(session, true, msg, sz)
|
response = cluster.packresponse(session, true, msg, sz)
|
||||||
|
if type(response) == "table" then
|
||||||
|
for _, v in ipairs(response) do
|
||||||
|
socket.lwrite(fd, v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
socket.write(fd, response)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
response = cluster.packresponse(session, false, msg)
|
response = cluster.packresponse(session, false, msg)
|
||||||
|
socket.write(fd, response)
|
||||||
end
|
end
|
||||||
socket.write(fd, response)
|
|
||||||
elseif subcmd == "open" then
|
elseif subcmd == "open" then
|
||||||
skynet.error(string.format("socket accept from %s", msg))
|
skynet.error(string.format("socket accept from %s", msg))
|
||||||
skynet.call(source, "lua", "accept", fd)
|
skynet.call(source, "lua", "accept", fd)
|
||||||
else
|
else
|
||||||
|
large_request = {}
|
||||||
skynet.error(string.format("socket %s %d : %s", subcmd, fd, msg))
|
skynet.error(string.format("socket %s %d : %s", subcmd, fd, msg))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ local skynet = require "skynet"
|
|||||||
local memory = require "memory"
|
local memory = require "memory"
|
||||||
|
|
||||||
memory.dumpinfo()
|
memory.dumpinfo()
|
||||||
memory.dump()
|
--memory.dump()
|
||||||
|
local info = memory.info()
|
||||||
|
for k,v in pairs(info) do
|
||||||
|
print(string.format(":%08x %gK",k,v/1024))
|
||||||
|
end
|
||||||
|
|
||||||
print("Total memory:", memory.total())
|
print("Total memory:", memory.total())
|
||||||
print("Total block:", memory.block())
|
print("Total block:", memory.block())
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ function COMMAND.debug(address, fd)
|
|||||||
skynet.fork(function()
|
skynet.fork(function()
|
||||||
repeat
|
repeat
|
||||||
local cmdline = socket.readline(fd, "\n")
|
local cmdline = socket.readline(fd, "\n")
|
||||||
|
cmdline = cmdline:gsub("(.*)\r$", "%1")
|
||||||
if not cmdline then
|
if not cmdline then
|
||||||
skynet.send(agent, "lua", "cmd", "cont")
|
skynet.send(agent, "lua", "cmd", "cont")
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ function handler.error(fd, msg)
|
|||||||
skynet.send(watchdog, "lua", "socket", "error", fd, msg)
|
skynet.send(watchdog, "lua", "socket", "error", fd, msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function handler.warning(fd, size)
|
||||||
|
skynet.send(watchdog, "lua", "socket", "warning", fd, size)
|
||||||
|
end
|
||||||
|
|
||||||
local CMD = {}
|
local CMD = {}
|
||||||
|
|
||||||
function CMD.forward(source, fd, client, address)
|
function CMD.forward(source, fd, client, address)
|
||||||
|
|||||||
14
skynet-src/atomic.h
Normal file
14
skynet-src/atomic.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef SKYNET_ATOMIC_H
|
||||||
|
#define SKYNET_ATOMIC_H
|
||||||
|
|
||||||
|
#define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval)
|
||||||
|
#define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval)
|
||||||
|
#define ATOM_INC(ptr) __sync_add_and_fetch(ptr, 1)
|
||||||
|
#define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1)
|
||||||
|
#define ATOM_DEC(ptr) __sync_sub_and_fetch(ptr, 1)
|
||||||
|
#define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1)
|
||||||
|
#define ATOM_ADD(ptr,n) __sync_add_and_fetch(ptr, n)
|
||||||
|
#define ATOM_SUB(ptr,n) __sync_sub_and_fetch(ptr, n)
|
||||||
|
#define ATOM_AND(ptr,n) __sync_and_and_fetch(ptr, n)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,9 +2,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
#include "malloc_hook.h"
|
#include "malloc_hook.h"
|
||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
static size_t _used_memory = 0;
|
static size_t _used_memory = 0;
|
||||||
static size_t _memory_block = 0;
|
static size_t _memory_block = 0;
|
||||||
@@ -31,11 +33,11 @@ get_allocated_field(uint32_t handle) {
|
|||||||
ssize_t old_alloc = data->allocated;
|
ssize_t old_alloc = data->allocated;
|
||||||
if(old_handle == 0 || old_alloc <= 0) {
|
if(old_handle == 0 || old_alloc <= 0) {
|
||||||
// data->allocated may less than zero, because it may not count at start.
|
// data->allocated may less than zero, because it may not count at start.
|
||||||
if(!__sync_bool_compare_and_swap(&data->handle, old_handle, handle)) {
|
if(!ATOM_CAS(&data->handle, old_handle, handle)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (old_alloc < 0) {
|
if (old_alloc < 0) {
|
||||||
__sync_bool_compare_and_swap(&data->allocated, old_alloc, 0);
|
ATOM_CAS(&data->allocated, old_alloc, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(data->handle != handle) {
|
if(data->handle != handle) {
|
||||||
@@ -46,21 +48,21 @@ get_allocated_field(uint32_t handle) {
|
|||||||
|
|
||||||
inline static void
|
inline static void
|
||||||
update_xmalloc_stat_alloc(uint32_t handle, size_t __n) {
|
update_xmalloc_stat_alloc(uint32_t handle, size_t __n) {
|
||||||
__sync_add_and_fetch(&_used_memory, __n);
|
ATOM_ADD(&_used_memory, __n);
|
||||||
__sync_add_and_fetch(&_memory_block, 1);
|
ATOM_INC(&_memory_block);
|
||||||
ssize_t* allocated = get_allocated_field(handle);
|
ssize_t* allocated = get_allocated_field(handle);
|
||||||
if(allocated) {
|
if(allocated) {
|
||||||
__sync_add_and_fetch(allocated, __n);
|
ATOM_ADD(allocated, __n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void
|
inline static void
|
||||||
update_xmalloc_stat_free(uint32_t handle, size_t __n) {
|
update_xmalloc_stat_free(uint32_t handle, size_t __n) {
|
||||||
__sync_sub_and_fetch(&_used_memory, __n);
|
ATOM_SUB(&_used_memory, __n);
|
||||||
__sync_sub_and_fetch(&_memory_block, 1);
|
ATOM_DEC(&_memory_block);
|
||||||
ssize_t* allocated = get_allocated_field(handle);
|
ssize_t* allocated = get_allocated_field(handle);
|
||||||
if(allocated) {
|
if(allocated) {
|
||||||
__sync_sub_and_fetch(allocated, __n);
|
ATOM_SUB(allocated, __n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,3 +226,17 @@ skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) {
|
|||||||
return skynet_realloc(ptr, nsize);
|
return skynet_realloc(ptr, nsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dump_mem_lua(lua_State *L) {
|
||||||
|
int i;
|
||||||
|
lua_newtable(L);
|
||||||
|
for(i=0; i<SLOT_SIZE; i++) {
|
||||||
|
mem_data* data = &mem_stats[i];
|
||||||
|
if(data->handle != 0 && data->allocated != 0) {
|
||||||
|
lua_pushinteger(L, data->allocated);
|
||||||
|
lua_rawseti(L, -2, (lua_Integer)data->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define SKYNET_MALLOC_HOOK_H
|
#define SKYNET_MALLOC_HOOK_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
extern size_t malloc_used_memory(void);
|
extern size_t malloc_used_memory(void);
|
||||||
extern size_t malloc_memory_block(void);
|
extern size_t malloc_memory_block(void);
|
||||||
@@ -9,6 +10,7 @@ extern void memory_info_dump(void);
|
|||||||
extern size_t mallctl_int64(const char* name, size_t* newval);
|
extern size_t mallctl_int64(const char* name, size_t* newval);
|
||||||
extern int mallctl_opt(const char* name, int* newval);
|
extern int mallctl_opt(const char* name, int* newval);
|
||||||
extern void dump_c_mem(void);
|
extern void dump_c_mem(void);
|
||||||
|
extern int dump_mem_lua(lua_State *L);
|
||||||
|
|
||||||
#endif /* SKYNET_MALLOC_HOOK_H */
|
#endif /* SKYNET_MALLOC_HOOK_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef SKYNET_RWLOCK_H
|
#ifndef SKYNET_RWLOCK_H
|
||||||
#define SKYNET_RWLOCK_H
|
#define SKYNET_RWLOCK_H
|
||||||
|
|
||||||
|
#ifndef USE_PTHREAD_LOCK
|
||||||
|
|
||||||
struct rwlock {
|
struct rwlock {
|
||||||
int write;
|
int write;
|
||||||
int read;
|
int read;
|
||||||
@@ -45,4 +47,42 @@ rwlock_runlock(struct rwlock *lock) {
|
|||||||
__sync_sub_and_fetch(&lock->read,1);
|
__sync_sub_and_fetch(&lock->read,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// only for some platform doesn't have __sync_*
|
||||||
|
// todo: check the result of pthread api
|
||||||
|
|
||||||
|
struct rwlock {
|
||||||
|
pthread_rwlock_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rwlock_init(struct rwlock *lock) {
|
||||||
|
pthread_rwlock_init(&lock->lock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rwlock_rlock(struct rwlock *lock) {
|
||||||
|
pthread_rwlock_rdlock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rwlock_wlock(struct rwlock *lock) {
|
||||||
|
pthread_rwlock_wrlock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rwlock_wunlock(struct rwlock *lock) {
|
||||||
|
pthread_rwlock_unlock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rwlock_runlock(struct rwlock *lock) {
|
||||||
|
pthread_rwlock_unlock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
#include "skynet_env.h"
|
#include "skynet_env.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
@@ -8,18 +9,15 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
struct skynet_env {
|
struct skynet_env {
|
||||||
int lock;
|
struct spinlock lock;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct skynet_env *E = NULL;
|
static struct skynet_env *E = NULL;
|
||||||
|
|
||||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
|
||||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
skynet_getenv(const char *key) {
|
skynet_getenv(const char *key) {
|
||||||
LOCK(E)
|
SPIN_LOCK(E)
|
||||||
|
|
||||||
lua_State *L = E->L;
|
lua_State *L = E->L;
|
||||||
|
|
||||||
@@ -27,14 +25,14 @@ skynet_getenv(const char *key) {
|
|||||||
const char * result = lua_tostring(L, -1);
|
const char * result = lua_tostring(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
UNLOCK(E)
|
SPIN_UNLOCK(E)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_setenv(const char *key, const char *value) {
|
skynet_setenv(const char *key, const char *value) {
|
||||||
LOCK(E)
|
SPIN_LOCK(E)
|
||||||
|
|
||||||
lua_State *L = E->L;
|
lua_State *L = E->L;
|
||||||
lua_getglobal(L, key);
|
lua_getglobal(L, key);
|
||||||
@@ -43,12 +41,12 @@ skynet_setenv(const char *key, const char *value) {
|
|||||||
lua_pushstring(L,value);
|
lua_pushstring(L,value);
|
||||||
lua_setglobal(L,key);
|
lua_setglobal(L,key);
|
||||||
|
|
||||||
UNLOCK(E)
|
SPIN_UNLOCK(E)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_env_init() {
|
skynet_env_init() {
|
||||||
E = skynet_malloc(sizeof(*E));
|
E = skynet_malloc(sizeof(*E));
|
||||||
E->lock = 0;
|
SPIN_INIT(E)
|
||||||
E->L = luaL_newstate();
|
E->L = luaL_newstate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ skynet_error(struct skynet_context * context, const char *msg, ...) {
|
|||||||
}
|
}
|
||||||
smsg.session = 0;
|
smsg.session = 0;
|
||||||
smsg.data = data;
|
smsg.data = data;
|
||||||
smsg.sz = len | (PTYPE_TEXT << HANDLE_REMOTE_SHIFT);
|
smsg.sz = len | ((size_t)PTYPE_TEXT << MESSAGE_TYPE_SHIFT);
|
||||||
skynet_context_push(logger, &smsg);
|
skynet_context_push(logger, &smsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "skynet_harbor.h"
|
// reserve high 8 bits for remote id
|
||||||
|
#define HANDLE_MASK 0xffffff
|
||||||
|
#define HANDLE_REMOTE_SHIFT 24
|
||||||
|
|
||||||
struct skynet_context;
|
struct skynet_context;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
#include "skynet_harbor.h"
|
#include "skynet_harbor.h"
|
||||||
#include "skynet_server.h"
|
#include "skynet_server.h"
|
||||||
|
#include "skynet_mq.h"
|
||||||
|
#include "skynet_handle.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -11,8 +13,8 @@ static unsigned int HARBOR = ~0;
|
|||||||
|
|
||||||
void
|
void
|
||||||
skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session) {
|
skynet_harbor_send(struct remote_message *rmsg, uint32_t source, int session) {
|
||||||
int type = rmsg->sz >> HANDLE_REMOTE_SHIFT;
|
int type = rmsg->sz >> MESSAGE_TYPE_SHIFT;
|
||||||
rmsg->sz &= HANDLE_MASK;
|
rmsg->sz &= MESSAGE_TYPE_MASK;
|
||||||
assert(type != PTYPE_SYSTEM && type != PTYPE_HARBOR && REMOTE);
|
assert(type != PTYPE_SYSTEM && type != PTYPE_HARBOR && REMOTE);
|
||||||
skynet_context_send(REMOTE, rmsg, sizeof(*rmsg) , source, type , session);
|
skynet_context_send(REMOTE, rmsg, sizeof(*rmsg) , source, type , session);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
#define GLOBALNAME_LENGTH 16
|
#define GLOBALNAME_LENGTH 16
|
||||||
#define REMOTE_MAX 256
|
#define REMOTE_MAX 256
|
||||||
|
|
||||||
// reserve high 8 bits for remote id
|
|
||||||
#define HANDLE_MASK 0xffffff
|
|
||||||
#define HANDLE_REMOTE_SHIFT 24
|
|
||||||
|
|
||||||
struct remote_name {
|
struct remote_name {
|
||||||
char name[GLOBALNAME_LENGTH];
|
char name[GLOBALNAME_LENGTH];
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
|
|
||||||
#include "skynet_module.h"
|
#include "skynet_module.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
|
|
||||||
struct modules {
|
struct modules {
|
||||||
int count;
|
int count;
|
||||||
int lock;
|
struct spinlock lock;
|
||||||
const char * path;
|
const char * path;
|
||||||
struct skynet_module m[MAX_MODULE_TYPE];
|
struct skynet_module m[MAX_MODULE_TYPE];
|
||||||
};
|
};
|
||||||
@@ -95,7 +96,7 @@ skynet_module_query(const char * name) {
|
|||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
while(__sync_lock_test_and_set(&M->lock,1)) {}
|
SPIN_LOCK(M)
|
||||||
|
|
||||||
result = _query(name); // double check
|
result = _query(name); // double check
|
||||||
|
|
||||||
@@ -114,21 +115,22 @@ skynet_module_query(const char * name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__sync_lock_release(&M->lock);
|
SPIN_UNLOCK(M)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_module_insert(struct skynet_module *mod) {
|
skynet_module_insert(struct skynet_module *mod) {
|
||||||
while(__sync_lock_test_and_set(&M->lock,1)) {}
|
SPIN_LOCK(M)
|
||||||
|
|
||||||
struct skynet_module * m = _query(mod->name);
|
struct skynet_module * m = _query(mod->name);
|
||||||
assert(m == NULL && M->count < MAX_MODULE_TYPE);
|
assert(m == NULL && M->count < MAX_MODULE_TYPE);
|
||||||
int index = M->count;
|
int index = M->count;
|
||||||
M->m[index] = *mod;
|
M->m[index] = *mod;
|
||||||
++M->count;
|
++M->count;
|
||||||
__sync_lock_release(&M->lock);
|
|
||||||
|
SPIN_UNLOCK(M)
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@@ -164,7 +166,8 @@ skynet_module_init(const char *path) {
|
|||||||
struct modules *m = skynet_malloc(sizeof(*m));
|
struct modules *m = skynet_malloc(sizeof(*m));
|
||||||
m->count = 0;
|
m->count = 0;
|
||||||
m->path = skynet_strdup(path);
|
m->path = skynet_strdup(path);
|
||||||
m->lock = 0;
|
|
||||||
|
SPIN_INIT(m)
|
||||||
|
|
||||||
M = m;
|
M = m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "skynet_monitor.h"
|
#include "skynet_monitor.h"
|
||||||
#include "skynet_server.h"
|
#include "skynet_server.h"
|
||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -30,7 +31,7 @@ void
|
|||||||
skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) {
|
skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) {
|
||||||
sm->source = source;
|
sm->source = source;
|
||||||
sm->destination = destination;
|
sm->destination = destination;
|
||||||
__sync_fetch_and_add(&sm->version , 1);
|
ATOM_INC(&sm->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "skynet.h"
|
#include "skynet.h"
|
||||||
#include "skynet_mq.h"
|
#include "skynet_mq.h"
|
||||||
#include "skynet_handle.h"
|
#include "skynet_handle.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -18,11 +19,11 @@
|
|||||||
#define MQ_OVERLOAD 1024
|
#define MQ_OVERLOAD 1024
|
||||||
|
|
||||||
struct message_queue {
|
struct message_queue {
|
||||||
|
struct spinlock lock;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
int cap;
|
int cap;
|
||||||
int head;
|
int head;
|
||||||
int tail;
|
int tail;
|
||||||
int lock;
|
|
||||||
int release;
|
int release;
|
||||||
int in_global;
|
int in_global;
|
||||||
int overload;
|
int overload;
|
||||||
@@ -34,19 +35,16 @@ struct message_queue {
|
|||||||
struct global_queue {
|
struct global_queue {
|
||||||
struct message_queue *head;
|
struct message_queue *head;
|
||||||
struct message_queue *tail;
|
struct message_queue *tail;
|
||||||
int lock;
|
struct spinlock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct global_queue *Q = NULL;
|
static struct global_queue *Q = NULL;
|
||||||
|
|
||||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
|
||||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_globalmq_push(struct message_queue * queue) {
|
skynet_globalmq_push(struct message_queue * queue) {
|
||||||
struct global_queue *q= Q;
|
struct global_queue *q= Q;
|
||||||
|
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
assert(queue->next == NULL);
|
assert(queue->next == NULL);
|
||||||
if(q->tail) {
|
if(q->tail) {
|
||||||
q->tail->next = queue;
|
q->tail->next = queue;
|
||||||
@@ -54,14 +52,14 @@ skynet_globalmq_push(struct message_queue * queue) {
|
|||||||
} else {
|
} else {
|
||||||
q->head = q->tail = queue;
|
q->head = q->tail = queue;
|
||||||
}
|
}
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct message_queue *
|
struct message_queue *
|
||||||
skynet_globalmq_pop() {
|
skynet_globalmq_pop() {
|
||||||
struct global_queue *q = Q;
|
struct global_queue *q = Q;
|
||||||
|
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
struct message_queue *mq = q->head;
|
struct message_queue *mq = q->head;
|
||||||
if(mq) {
|
if(mq) {
|
||||||
q->head = mq->next;
|
q->head = mq->next;
|
||||||
@@ -71,7 +69,7 @@ skynet_globalmq_pop() {
|
|||||||
}
|
}
|
||||||
mq->next = NULL;
|
mq->next = NULL;
|
||||||
}
|
}
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
|
|
||||||
return mq;
|
return mq;
|
||||||
}
|
}
|
||||||
@@ -83,7 +81,7 @@ skynet_mq_create(uint32_t handle) {
|
|||||||
q->cap = DEFAULT_QUEUE_SIZE;
|
q->cap = DEFAULT_QUEUE_SIZE;
|
||||||
q->head = 0;
|
q->head = 0;
|
||||||
q->tail = 0;
|
q->tail = 0;
|
||||||
q->lock = 0;
|
SPIN_INIT(q)
|
||||||
// When the queue is create (always between service create and service init) ,
|
// When the queue is create (always between service create and service init) ,
|
||||||
// set in_global flag to avoid push it to global queue .
|
// set in_global flag to avoid push it to global queue .
|
||||||
// If the service init success, skynet_context_new will call skynet_mq_force_push to push it to global queue.
|
// If the service init success, skynet_context_new will call skynet_mq_force_push to push it to global queue.
|
||||||
@@ -100,6 +98,7 @@ skynet_mq_create(uint32_t handle) {
|
|||||||
static void
|
static void
|
||||||
_release(struct message_queue *q) {
|
_release(struct message_queue *q) {
|
||||||
assert(q->next == NULL);
|
assert(q->next == NULL);
|
||||||
|
SPIN_DESTROY(q)
|
||||||
skynet_free(q->queue);
|
skynet_free(q->queue);
|
||||||
skynet_free(q);
|
skynet_free(q);
|
||||||
}
|
}
|
||||||
@@ -113,11 +112,11 @@ int
|
|||||||
skynet_mq_length(struct message_queue *q) {
|
skynet_mq_length(struct message_queue *q) {
|
||||||
int head, tail,cap;
|
int head, tail,cap;
|
||||||
|
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
head = q->head;
|
head = q->head;
|
||||||
tail = q->tail;
|
tail = q->tail;
|
||||||
cap = q->cap;
|
cap = q->cap;
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
|
|
||||||
if (head <= tail) {
|
if (head <= tail) {
|
||||||
return tail - head;
|
return tail - head;
|
||||||
@@ -138,7 +137,7 @@ skynet_mq_overload(struct message_queue *q) {
|
|||||||
int
|
int
|
||||||
skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
|
skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
|
|
||||||
if (q->head != q->tail) {
|
if (q->head != q->tail) {
|
||||||
*message = q->queue[q->head++];
|
*message = q->queue[q->head++];
|
||||||
@@ -167,7 +166,7 @@ skynet_mq_pop(struct message_queue *q, struct skynet_message *message) {
|
|||||||
q->in_global = 0;
|
q->in_global = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -190,7 +189,7 @@ expand_queue(struct message_queue *q) {
|
|||||||
void
|
void
|
||||||
skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
|
skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
|
||||||
assert(message);
|
assert(message);
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
|
|
||||||
q->queue[q->tail] = *message;
|
q->queue[q->tail] = *message;
|
||||||
if (++ q->tail >= q->cap) {
|
if (++ q->tail >= q->cap) {
|
||||||
@@ -206,25 +205,26 @@ skynet_mq_push(struct message_queue *q, struct skynet_message *message) {
|
|||||||
skynet_globalmq_push(q);
|
skynet_globalmq_push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_mq_init() {
|
skynet_mq_init() {
|
||||||
struct global_queue *q = skynet_malloc(sizeof(*q));
|
struct global_queue *q = skynet_malloc(sizeof(*q));
|
||||||
memset(q,0,sizeof(*q));
|
memset(q,0,sizeof(*q));
|
||||||
|
SPIN_INIT(q);
|
||||||
Q=q;
|
Q=q;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skynet_mq_mark_release(struct message_queue *q) {
|
skynet_mq_mark_release(struct message_queue *q) {
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
assert(q->release == 0);
|
assert(q->release == 0);
|
||||||
q->release = 1;
|
q->release = 1;
|
||||||
if (q->in_global != MQ_IN_GLOBAL) {
|
if (q->in_global != MQ_IN_GLOBAL) {
|
||||||
skynet_globalmq_push(q);
|
skynet_globalmq_push(q);
|
||||||
}
|
}
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -238,13 +238,13 @@ _drop_queue(struct message_queue *q, message_drop drop_func, void *ud) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
skynet_mq_release(struct message_queue *q, message_drop drop_func, void *ud) {
|
skynet_mq_release(struct message_queue *q, message_drop drop_func, void *ud) {
|
||||||
LOCK(q)
|
SPIN_LOCK(q)
|
||||||
|
|
||||||
if (q->release) {
|
if (q->release) {
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
_drop_queue(q, drop_func, ud);
|
_drop_queue(q, drop_func, ud);
|
||||||
} else {
|
} else {
|
||||||
skynet_globalmq_push(q);
|
skynet_globalmq_push(q);
|
||||||
UNLOCK(q)
|
SPIN_UNLOCK(q)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ struct skynet_message {
|
|||||||
size_t sz;
|
size_t sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// type is encoding in skynet_message.sz high 8bit
|
||||||
|
#define MESSAGE_TYPE_MASK (SIZE_MAX >> 8)
|
||||||
|
#define MESSAGE_TYPE_SHIFT ((sizeof(size_t)-1) * 8)
|
||||||
|
|
||||||
struct message_queue;
|
struct message_queue;
|
||||||
|
|
||||||
void skynet_globalmq_push(struct message_queue * queue);
|
void skynet_globalmq_push(struct message_queue * queue);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "skynet_monitor.h"
|
#include "skynet_monitor.h"
|
||||||
#include "skynet_imp.h"
|
#include "skynet_imp.h"
|
||||||
#include "skynet_log.h"
|
#include "skynet_log.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@@ -21,16 +23,18 @@
|
|||||||
|
|
||||||
#ifdef CALLING_CHECK
|
#ifdef CALLING_CHECK
|
||||||
|
|
||||||
#define CHECKCALLING_BEGIN(ctx) assert(__sync_lock_test_and_set(&ctx->calling,1) == 0);
|
#define CHECKCALLING_BEGIN(ctx) if (!(spinlock_trylock(&ctx->calling))) { assert(0); }
|
||||||
#define CHECKCALLING_END(ctx) __sync_lock_release(&ctx->calling);
|
#define CHECKCALLING_END(ctx) spinlock_unlock(&ctx->calling);
|
||||||
#define CHECKCALLING_INIT(ctx) ctx->calling = 0;
|
#define CHECKCALLING_INIT(ctx) spinlock_init(&ctx->calling);
|
||||||
#define CHECKCALLING_DECL int calling;
|
#define CHECKCALLING_DESTROY(ctx) spinlock_destroy(&ctx->calling);
|
||||||
|
#define CHECKCALLING_DECL struct spinlock calling;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define CHECKCALLING_BEGIN(ctx)
|
#define CHECKCALLING_BEGIN(ctx)
|
||||||
#define CHECKCALLING_END(ctx)
|
#define CHECKCALLING_END(ctx)
|
||||||
#define CHECKCALLING_INIT(ctx)
|
#define CHECKCALLING_INIT(ctx)
|
||||||
|
#define CHECKCALLING_DESTROY(ctx)
|
||||||
#define CHECKCALLING_DECL
|
#define CHECKCALLING_DECL
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -68,12 +72,12 @@ skynet_context_total() {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
context_inc() {
|
context_inc() {
|
||||||
__sync_fetch_and_add(&G_NODE.total,1);
|
ATOM_INC(&G_NODE.total);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
context_dec() {
|
context_dec() {
|
||||||
__sync_fetch_and_sub(&G_NODE.total,1);
|
ATOM_DEC(&G_NODE.total);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
@@ -179,7 +183,7 @@ skynet_context_newsession(struct skynet_context *ctx) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
skynet_context_grab(struct skynet_context *ctx) {
|
skynet_context_grab(struct skynet_context *ctx) {
|
||||||
__sync_add_and_fetch(&ctx->ref,1);
|
ATOM_INC(&ctx->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -197,13 +201,14 @@ delete_context(struct skynet_context *ctx) {
|
|||||||
}
|
}
|
||||||
skynet_module_instance_release(ctx->mod, ctx->instance);
|
skynet_module_instance_release(ctx->mod, ctx->instance);
|
||||||
skynet_mq_mark_release(ctx->queue);
|
skynet_mq_mark_release(ctx->queue);
|
||||||
|
CHECKCALLING_DESTROY(ctx)
|
||||||
skynet_free(ctx);
|
skynet_free(ctx);
|
||||||
context_dec();
|
context_dec();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct skynet_context *
|
struct skynet_context *
|
||||||
skynet_context_release(struct skynet_context *ctx) {
|
skynet_context_release(struct skynet_context *ctx) {
|
||||||
if (__sync_sub_and_fetch(&ctx->ref,1) == 0) {
|
if (ATOM_DEC(&ctx->ref) == 0) {
|
||||||
delete_context(ctx);
|
delete_context(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -246,8 +251,8 @@ dispatch_message(struct skynet_context *ctx, struct skynet_message *msg) {
|
|||||||
assert(ctx->init);
|
assert(ctx->init);
|
||||||
CHECKCALLING_BEGIN(ctx)
|
CHECKCALLING_BEGIN(ctx)
|
||||||
pthread_setspecific(G_NODE.handle_key, (void *)(uintptr_t)(ctx->handle));
|
pthread_setspecific(G_NODE.handle_key, (void *)(uintptr_t)(ctx->handle));
|
||||||
int type = msg->sz >> HANDLE_REMOTE_SHIFT;
|
int type = msg->sz >> MESSAGE_TYPE_SHIFT;
|
||||||
size_t sz = msg->sz & HANDLE_MASK;
|
size_t sz = msg->sz & MESSAGE_TYPE_MASK;
|
||||||
if (ctx->logfile) {
|
if (ctx->logfile) {
|
||||||
skynet_log_output(ctx->logfile, msg->source, type, msg->session, msg->data, sz);
|
skynet_log_output(ctx->logfile, msg->source, type, msg->session, msg->data, sz);
|
||||||
}
|
}
|
||||||
@@ -560,7 +565,7 @@ cmd_logon(struct skynet_context * context, const char * param) {
|
|||||||
if (lastf == NULL) {
|
if (lastf == NULL) {
|
||||||
f = skynet_log_open(context, handle);
|
f = skynet_log_open(context, handle);
|
||||||
if (f) {
|
if (f) {
|
||||||
if (!__sync_bool_compare_and_swap(&ctx->logfile, NULL, f)) {
|
if (!ATOM_CAS_POINTER(&ctx->logfile, NULL, f)) {
|
||||||
// logfile opens in other thread, close this one.
|
// logfile opens in other thread, close this one.
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
@@ -581,7 +586,7 @@ cmd_logoff(struct skynet_context * context, const char * param) {
|
|||||||
FILE * f = ctx->logfile;
|
FILE * f = ctx->logfile;
|
||||||
if (f) {
|
if (f) {
|
||||||
// logfile may close in other thread
|
// logfile may close in other thread
|
||||||
if (__sync_bool_compare_and_swap(&ctx->logfile, f, NULL)) {
|
if (ATOM_CAS_POINTER(&ctx->logfile, f, NULL)) {
|
||||||
skynet_log_close(context, f, handle);
|
skynet_log_close(context, f, handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,13 +667,13 @@ _filter_args(struct skynet_context * context, int type, int *session, void ** da
|
|||||||
*data = msg;
|
*data = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sz |= type << HANDLE_REMOTE_SHIFT;
|
*sz |= (size_t)type << MESSAGE_TYPE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
skynet_send(struct skynet_context * context, uint32_t source, uint32_t destination , int type, int session, void * data, size_t sz) {
|
skynet_send(struct skynet_context * context, uint32_t source, uint32_t destination , int type, int session, void * data, size_t sz) {
|
||||||
if ((sz & HANDLE_MASK) != sz) {
|
if ((sz & MESSAGE_TYPE_MASK) != sz) {
|
||||||
skynet_error(context, "The message to %x is too large (sz = %lu)", destination, sz);
|
skynet_error(context, "The message to %x is too large", destination);
|
||||||
skynet_free(data);
|
skynet_free(data);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -751,7 +756,7 @@ skynet_context_send(struct skynet_context * ctx, void * msg, size_t sz, uint32_t
|
|||||||
smsg.source = source;
|
smsg.source = source;
|
||||||
smsg.session = session;
|
smsg.session = session;
|
||||||
smsg.data = msg;
|
smsg.data = msg;
|
||||||
smsg.sz = sz | type << HANDLE_REMOTE_SHIFT;
|
smsg.sz = sz | (size_t)type << MESSAGE_TYPE_SHIFT;
|
||||||
|
|
||||||
skynet_mq_push(ctx->queue, &smsg);
|
skynet_mq_push(ctx->queue, &smsg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ skynet_socket_free() {
|
|||||||
static void
|
static void
|
||||||
forward_message(int type, bool padding, struct socket_message * result) {
|
forward_message(int type, bool padding, struct socket_message * result) {
|
||||||
struct skynet_socket_message *sm;
|
struct skynet_socket_message *sm;
|
||||||
int sz = sizeof(*sm);
|
size_t sz = sizeof(*sm);
|
||||||
if (padding) {
|
if (padding) {
|
||||||
if (result->data) {
|
if (result->data) {
|
||||||
sz += strlen(result->data);
|
sz += strlen(result->data);
|
||||||
@@ -56,7 +56,7 @@ forward_message(int type, bool padding, struct socket_message * result) {
|
|||||||
message.source = 0;
|
message.source = 0;
|
||||||
message.session = 0;
|
message.session = 0;
|
||||||
message.data = sm;
|
message.data = sm;
|
||||||
message.sz = sz | PTYPE_SOCKET << HANDLE_REMOTE_SHIFT;
|
message.sz = sz | ((size_t)PTYPE_SOCKET << MESSAGE_TYPE_SHIFT);
|
||||||
|
|
||||||
if (skynet_context_push((uint32_t)result->opaque, &message)) {
|
if (skynet_context_push((uint32_t)result->opaque, &message)) {
|
||||||
// todo: report somewhere to close socket
|
// todo: report somewhere to close socket
|
||||||
@@ -109,10 +109,13 @@ check_wsz(struct skynet_context *ctx, int id, void *buffer, int64_t wsz) {
|
|||||||
if (wsz < 0) {
|
if (wsz < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (wsz > 1024 * 1024) {
|
} else if (wsz > 1024 * 1024) {
|
||||||
int kb4 = wsz / 1024 / 4;
|
struct skynet_socket_message tmp;
|
||||||
if (kb4 % 256 == 0) {
|
tmp.type = SKYNET_SOCKET_TYPE_WARNING;
|
||||||
skynet_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id);
|
tmp.id = id;
|
||||||
}
|
tmp.ud = (int)(wsz / 1024);
|
||||||
|
tmp.buffer = NULL;
|
||||||
|
skynet_send(ctx, 0, skynet_context_handle(ctx), PTYPE_SOCKET, 0 , &tmp, sizeof(tmp));
|
||||||
|
// skynet_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ struct skynet_context;
|
|||||||
#define SKYNET_SOCKET_TYPE_ACCEPT 4
|
#define SKYNET_SOCKET_TYPE_ACCEPT 4
|
||||||
#define SKYNET_SOCKET_TYPE_ERROR 5
|
#define SKYNET_SOCKET_TYPE_ERROR 5
|
||||||
#define SKYNET_SOCKET_TYPE_UDP 6
|
#define SKYNET_SOCKET_TYPE_UDP 6
|
||||||
|
#define SKYNET_SOCKET_TYPE_WARNING 7
|
||||||
|
|
||||||
struct skynet_socket_message {
|
struct skynet_socket_message {
|
||||||
int type;
|
int type;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "skynet_monitor.h"
|
#include "skynet_monitor.h"
|
||||||
#include "skynet_socket.h"
|
#include "skynet_socket.h"
|
||||||
#include "skynet_daemon.h"
|
#include "skynet_daemon.h"
|
||||||
|
#include "skynet_harbor.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "skynet_mq.h"
|
#include "skynet_mq.h"
|
||||||
#include "skynet_server.h"
|
#include "skynet_server.h"
|
||||||
#include "skynet_handle.h"
|
#include "skynet_handle.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -17,9 +18,6 @@
|
|||||||
|
|
||||||
typedef void (*timer_execute_func)(void *ud,void *arg);
|
typedef void (*timer_execute_func)(void *ud,void *arg);
|
||||||
|
|
||||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
|
||||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
|
||||||
|
|
||||||
#define TIME_NEAR_SHIFT 8
|
#define TIME_NEAR_SHIFT 8
|
||||||
#define TIME_NEAR (1 << TIME_NEAR_SHIFT)
|
#define TIME_NEAR (1 << TIME_NEAR_SHIFT)
|
||||||
#define TIME_LEVEL_SHIFT 6
|
#define TIME_LEVEL_SHIFT 6
|
||||||
@@ -45,7 +43,7 @@ struct link_list {
|
|||||||
struct timer {
|
struct timer {
|
||||||
struct link_list near[TIME_NEAR];
|
struct link_list near[TIME_NEAR];
|
||||||
struct link_list t[4][TIME_LEVEL];
|
struct link_list t[4][TIME_LEVEL];
|
||||||
int lock;
|
struct spinlock lock;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
uint32_t current;
|
uint32_t current;
|
||||||
uint32_t starttime;
|
uint32_t starttime;
|
||||||
@@ -97,12 +95,12 @@ timer_add(struct timer *T,void *arg,size_t sz,int time) {
|
|||||||
struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz);
|
struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz);
|
||||||
memcpy(node+1,arg,sz);
|
memcpy(node+1,arg,sz);
|
||||||
|
|
||||||
LOCK(T);
|
SPIN_LOCK(T);
|
||||||
|
|
||||||
node->expire=time+T->time;
|
node->expire=time+T->time;
|
||||||
add_node(T,node);
|
add_node(T,node);
|
||||||
|
|
||||||
UNLOCK(T);
|
SPIN_UNLOCK(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -146,7 +144,7 @@ dispatch_list(struct timer_node *current) {
|
|||||||
message.source = 0;
|
message.source = 0;
|
||||||
message.session = event->session;
|
message.session = event->session;
|
||||||
message.data = NULL;
|
message.data = NULL;
|
||||||
message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT;
|
message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
|
||||||
|
|
||||||
skynet_context_push(event->handle, &message);
|
skynet_context_push(event->handle, &message);
|
||||||
|
|
||||||
@@ -162,16 +160,16 @@ timer_execute(struct timer *T) {
|
|||||||
|
|
||||||
while (T->near[idx].head.next) {
|
while (T->near[idx].head.next) {
|
||||||
struct timer_node *current = link_clear(&T->near[idx]);
|
struct timer_node *current = link_clear(&T->near[idx]);
|
||||||
UNLOCK(T);
|
SPIN_UNLOCK(T);
|
||||||
// dispatch_list don't need lock T
|
// dispatch_list don't need lock T
|
||||||
dispatch_list(current);
|
dispatch_list(current);
|
||||||
LOCK(T);
|
SPIN_LOCK(T);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
timer_update(struct timer *T) {
|
timer_update(struct timer *T) {
|
||||||
LOCK(T);
|
SPIN_LOCK(T);
|
||||||
|
|
||||||
// try to dispatch timeout 0 (rare condition)
|
// try to dispatch timeout 0 (rare condition)
|
||||||
timer_execute(T);
|
timer_execute(T);
|
||||||
@@ -181,7 +179,7 @@ timer_update(struct timer *T) {
|
|||||||
|
|
||||||
timer_execute(T);
|
timer_execute(T);
|
||||||
|
|
||||||
UNLOCK(T);
|
SPIN_UNLOCK(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timer *
|
static struct timer *
|
||||||
@@ -201,7 +199,8 @@ timer_create_timer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r->lock = 0;
|
SPIN_INIT(r)
|
||||||
|
|
||||||
r->current = 0;
|
r->current = 0;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -214,7 +213,7 @@ skynet_timeout(uint32_t handle, int time, int session) {
|
|||||||
message.source = 0;
|
message.source = 0;
|
||||||
message.session = session;
|
message.session = session;
|
||||||
message.data = NULL;
|
message.data = NULL;
|
||||||
message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT;
|
message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;
|
||||||
|
|
||||||
if (skynet_context_push(handle, &message)) {
|
if (skynet_context_push(handle, &message)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "socket_server.h"
|
#include "socket_server.h"
|
||||||
#include "socket_poll.h"
|
#include "socket_poll.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -237,13 +238,13 @@ static int
|
|||||||
reserve_id(struct socket_server *ss) {
|
reserve_id(struct socket_server *ss) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<MAX_SOCKET;i++) {
|
for (i=0;i<MAX_SOCKET;i++) {
|
||||||
int id = __sync_add_and_fetch(&(ss->alloc_id), 1);
|
int id = ATOM_INC(&(ss->alloc_id));
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
id = __sync_and_and_fetch(&(ss->alloc_id), 0x7fffffff);
|
id = ATOM_AND(&(ss->alloc_id), 0x7fffffff);
|
||||||
}
|
}
|
||||||
struct socket *s = &ss->slot[HASH_ID(id)];
|
struct socket *s = &ss->slot[HASH_ID(id)];
|
||||||
if (s->type == SOCKET_TYPE_INVALID) {
|
if (s->type == SOCKET_TYPE_INVALID) {
|
||||||
if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
|
if (ATOM_CAS(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
|
||||||
s->id = id;
|
s->id = id;
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
return id;
|
return id;
|
||||||
@@ -1265,7 +1266,7 @@ send_request(struct socket_server *ss, struct request_package *request, char typ
|
|||||||
static int
|
static int
|
||||||
open_request(struct socket_server *ss, struct request_package *req, uintptr_t opaque, const char *addr, int port) {
|
open_request(struct socket_server *ss, struct request_package *req, uintptr_t opaque, const char *addr, int port) {
|
||||||
int len = strlen(addr);
|
int len = strlen(addr);
|
||||||
if (len + sizeof(req->u.open) > 256) {
|
if (len + sizeof(req->u.open) >= 256) {
|
||||||
fprintf(stderr, "socket-server : Invalid addr %s.\n",addr);
|
fprintf(stderr, "socket-server : Invalid addr %s.\n",addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
77
skynet-src/spinlock.h
Normal file
77
skynet-src/spinlock.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef SKYNET_SPINLOCK_H
|
||||||
|
#define SKYNET_SPINLOCK_H
|
||||||
|
|
||||||
|
#define SPIN_INIT(q) spinlock_init(&(q)->lock);
|
||||||
|
#define SPIN_LOCK(q) spinlock_lock(&(q)->lock);
|
||||||
|
#define SPIN_UNLOCK(q) spinlock_unlock(&(q)->lock);
|
||||||
|
#define SPIN_DESTROY(q) spinlock_destroy(&(q)->lock);
|
||||||
|
|
||||||
|
#ifndef USE_PTHREAD_LOCK
|
||||||
|
|
||||||
|
struct spinlock {
|
||||||
|
int lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_init(struct spinlock *lock) {
|
||||||
|
lock->lock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_lock(struct spinlock *lock) {
|
||||||
|
while (__sync_lock_test_and_set(&lock->lock,1)) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
spinlock_trylock(struct spinlock *lock) {
|
||||||
|
return __sync_lock_test_and_set(&lock->lock,1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_unlock(struct spinlock *lock) {
|
||||||
|
__sync_lock_release(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_destroy(struct spinlock *lock) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// we use mutex instead of spinlock for some reason
|
||||||
|
// you can also replace to pthread_spinlock
|
||||||
|
|
||||||
|
struct spinlock {
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_init(struct spinlock *lock) {
|
||||||
|
pthread_mutex_init(&lock->lock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_lock(struct spinlock *lock) {
|
||||||
|
pthread_mutex_lock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
spinlock_trylock(struct spinlock *lock) {
|
||||||
|
return pthread_mutex_trylock(&lock->lock) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_unlock(struct spinlock *lock) {
|
||||||
|
pthread_mutex_unlock(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spinlock_destroy(struct spinlock *lock) {
|
||||||
|
pthread_mutex_destroy(&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user