diff --git a/GNUmakefile b/GNUmakefile index bf0a21d..810a90d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -116,7 +116,7 @@ rsm_tester: $(patsubst %.cc,%.o,$(rsm_tester)) rpc/librpc.a fuse.o: fuse.cc $(CXX) -c $(CXXFLAGS) $(FUSEFLAGS) $(MACFLAGS) $< -# mklab.inc is needed by 6.824 staff only. Just ignore it. +# mklab.inc is needed by staff only. Just ignore it. -include mklab.inc -include *.d @@ -128,10 +128,10 @@ clean: rm $(clean_files) -rf handin_ignore=$(clean_files) core* *log -handin_file=$(shell whoami)-lab$(LAB).tgz +handin_file=$(shell whoami)-lab$(LAB)-112037xxxx.tgz labdir=$(shell basename $(PWD)) handin: @if test -f stop.sh; then ./stop.sh > /dev/null 2>&1 | echo ""; fi @bash -c "cd ../; tar -X <(tr ' ' '\n' < <(echo '$(handin_ignore)')) -czvf $(handin_file) $(labdir); mv $(handin_file) $(labdir); cd $(labdir)" - @echo Please email $(handin_file) to 6.824-submit@pdos.csail.mit.edu + @echo Please change the name of $(handin_file) and email it to xiayubin@gmail.com @echo Thanks! diff --git a/lock_client.cc b/lock_client.cc index fadec9a..a45def1 100644 --- a/lock_client.cc +++ b/lock_client.cc @@ -30,10 +30,18 @@ lock_client::stat(lock_protocol::lockid_t lid) lock_protocol::status lock_client::acquire(lock_protocol::lockid_t lid) { + int r; + lock_protocol::status ret = cl->call(lock_protocol::acquire, cl->id(), lid, r); + VERIFY (ret == lock_protocol::OK); + return r; } lock_protocol::status lock_client::release(lock_protocol::lockid_t lid) { + int r; + lock_protocol::status ret = cl->call(lock_protocol::release, cl->id(), lid, r); + VERIFY (ret == lock_protocol::OK); + return r; } diff --git a/lock_server.cc b/lock_server.cc index 9365089..be9fdbe 100644 --- a/lock_server.cc +++ b/lock_server.cc @@ -9,6 +9,7 @@ lock_server::lock_server(): nacquire (0) { + VERIFY(pthread_mutex_init(&mutex, NULL) == 0); } lock_protocol::status @@ -17,7 +18,63 @@ lock_server::stat(int clt, lock_protocol::lockid_t lid, int &r) lock_protocol::status ret = lock_protocol::OK; printf("stat request from clt %d\n", clt); r = nacquire; + + if(locks.find(lid) != locks.end()) + r = locks[lid]; + return ret; +} + +lock_protocol::status +lock_server::acquire(int clt, lock_protocol::lockid_t lid, int &r) +{ + lock_protocol::status ret = lock_protocol::OK; + printf("acqure request from clt %d\n", clt); + r = nacquire; + + VERIFY(pthread_mutex_lock(&mutex) == 0); + + if(locks.find(lid) == locks.end()) + { + locks[lid] = clt; + // set variable condition + if(conds.find(lid) == conds.end()) + { + pthread_cond_t *p_cond = new pthread_cond_t(); + pthread_cond_init(p_cond, NULL); + conds[lid] = p_cond; + } + } + else + { + // TODO wait for the lock to be free + while(locks[lid]) + pthread_cond_wait(conds[lid], &mutex); + + locks[lid] = clt; + } + + r = clt; + VERIFY(pthread_mutex_unlock(&mutex) == 0); return ret; } +lock_protocol::status +lock_server::release(int clt, lock_protocol::lockid_t lid, int &r) +{ + lock_protocol::status ret = lock_protocol::OK; + printf("release request from clt %d\n", clt); + r = nacquire; + + VERIFY(pthread_mutex_lock(&mutex) == 0); + if(locks.find(lid) != locks.end()) + locks.erase(lid); + + if(conds.find(lid) != conds.end()) + pthread_cond_signal(conds[lid]); + + + VERIFY(pthread_mutex_unlock(&mutex) == 0); + r = clt; + return ret; +} diff --git a/lock_server.h b/lock_server.h index f8d34fe..f05a932 100644 --- a/lock_server.h +++ b/lock_server.h @@ -5,26 +5,29 @@ #define lock_server_h #include +#include +#include #include "lock_protocol.h" #include "lock_client.h" #include "rpc.h" +#include class lock_server { protected: int nacquire; + std::map locks; + std::map conds; + pthread_mutex_t mutex; + public: lock_server(); ~lock_server() {}; - lock_protocol::status stat(int clt, lock_protocol::lockid_t lid, int &); + lock_protocol::status stat(int clt, lock_protocol::lockid_t lid, int &); + lock_protocol::status acquire(int clt, lock_protocol::lockid_t lid, int &); + lock_protocol::status release(int clt, lock_protocol::lockid_t lid, int &); + }; #endif - - - - - - - diff --git a/lock_smain.cc b/lock_smain.cc index 72dac4a..c0e32a4 100644 --- a/lock_smain.cc +++ b/lock_smain.cc @@ -34,6 +34,9 @@ main(int argc, char *argv[]) lock_server ls; rpcs server(atoi(argv[1]), count); server.reg(lock_protocol::stat, &ls, &lock_server::stat); + server.reg(lock_protocol::acquire, &ls, &lock_server::acquire); + server.reg(lock_protocol::release, &ls, &lock_server::release); + #endif diff --git a/rpc/rpc.cc b/rpc/rpc.cc index 1c10850..c495502 100644 --- a/rpc/rpc.cc +++ b/rpc/rpc.cc @@ -627,8 +627,8 @@ rpcs::dispatch(djob_t *j) } break; case INPROGRESS: // server is working on this request - break; - case DONE: // duplicate and we still have the response + break; + case DONE: // duplicate and we still have the responsei c->send(b1, sz1); break; case FORGOTTEN: // very old request and we don't have the response anymore @@ -661,8 +661,44 @@ rpcs::checkduplicate_and_update(unsigned int clt_nonce, unsigned int xid, unsigned int xid_rep, char **b, int *sz) { ScopedLock rwl(&reply_window_m_); - // You fill this in for Lab 1. + if(max_rep[clt_nonce] < xid_rep) + max_rep[clt_nonce] = xid_rep; + std::list::iterator it = reply_window_[clt_nonce].begin(); + + int find = 0; + while(it != reply_window_[clt_nonce].end()) + { + if((*it).xid == xid) + { + if((*it).cb_present) + { + find = 1; + *b = (*it).buf; + *sz = (*it).sz; + } + else + find = 2; + ++it; + } + else if((*it).xid <= xid_rep) + { + free((*it).buf); + it = reply_window_[clt_nonce].erase(it); + } + else + ++it; + } + + if(find == 1) + return DONE; + else if(find == 2) + return INPROGRESS; + else if(xid <= max_rep[clt_nonce]) + return FORGOTTEN; + + reply_t reply(xid); + reply_window_[clt_nonce].push_back(reply); return NEW; } @@ -677,6 +713,12 @@ rpcs::add_reply(unsigned int clt_nonce, unsigned int xid, { ScopedLock rwl(&reply_window_m_); // You fill this in for Lab 1. + reply_t reply(xid); + reply.cb_present = true; + reply.buf = b; + reply.sz = sz; + + reply_window_[clt_nonce].push_back(reply); } void diff --git a/rpc/rpc.h b/rpc/rpc.h index 999810c..c37a082 100644 --- a/rpc/rpc.h +++ b/rpc/rpc.h @@ -298,6 +298,7 @@ class rpcs : public chanmgr { // per client that that client hasn't acknowledged receiving yet. // indexed by client nonce. std::map > reply_window_; + std::map max_rep; void free_reply_window(void); void add_reply(unsigned int clt_nonce, unsigned int xid, char *b, int sz);