コード例 #1
0
ファイル: sim-cache.c プロジェクト: mshzhb/ece552
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  int i;
  md_inst_t inst;
  register md_addr_t addr;
  enum md_opcode op;
  register int is_write;
  enum md_fault_type fault;

  fprintf(stderr, "sim: ** starting functional simulation w/ caches **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      if (itlb)
	cache_access(itlb, Read, IACOMPRESS(regs.regs_PC),
		     NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0);
      if (cache_il1)
	cache_access(cache_il1, Read, IACOMPRESS(regs.regs_PC),
		     NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0);
      MD_FETCH_INST(inst, mem, regs.regs_PC);

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)		\
	case OP:							\
          SYMCAT(OP,_IMPL);						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "machine.def"
	default:
          panic("attempted to execute a bogus opcode");
	}

      if (fault != md_fault_none)
	fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC);

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      /* update any stats tracked by PC */
      for (i=0; i < pcstat_nelt; i++)
	{
	  counter_t newval;
	  int delta;

	  /* check if any tracked stats changed */
	  newval = STATVAL(pcstat_stats[i]);
	  delta = newval - pcstat_lastvals[i];
	  if (delta != 0)
	    {
	      stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta);
	      pcstat_lastvals[i] = newval;
	    }

	}

      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}
コード例 #2
0
ファイル: sim-cache.c プロジェクト: mshzhb/ece552
/* register simulator-specific statistics */
void
sim_reg_stats(struct stat_sdb_t *sdb)	/* stats database */
{
  int i;

  /* register baseline stats */
  stat_reg_counter(sdb, "sim_num_insn",
		   "total number of instructions executed",
		   &sim_num_insn, sim_num_insn, NULL);
  stat_reg_counter(sdb, "sim_num_refs",
		   "total number of loads and stores executed",
		   &sim_num_refs, 0, NULL);
  stat_reg_int(sdb, "sim_elapsed_time",
	       "total simulation time in seconds",
	       &sim_elapsed_time, 0, NULL);
  stat_reg_formula(sdb, "sim_inst_rate",
		   "simulation speed (in insts/sec)",
		   "sim_num_insn / sim_elapsed_time", NULL);

  /* register cache stats */
  if (cache_il1
      && (cache_il1 != cache_dl1 && cache_il1 != cache_dl2))
    cache_reg_stats(cache_il1, sdb);
  if (cache_il2
      && (cache_il2 != cache_dl1 && cache_il2 != cache_dl2))
    cache_reg_stats(cache_il2, sdb);
  if (cache_dl1)
    cache_reg_stats(cache_dl1, sdb);
  if (cache_dl2)
    cache_reg_stats(cache_dl2, sdb);
  if (itlb)
    cache_reg_stats(itlb, sdb);
  if (dtlb)
    cache_reg_stats(dtlb, sdb);

  for (i=0; i<pcstat_nelt; i++)
    {
      char buf[512], buf1[512];
      struct stat_stat_t *stat;

      /* track the named statistical variable by text address */

      /* find it... */
      stat = stat_find_stat(sdb, pcstat_vars[i]);
      if (!stat)
	fatal("cannot locate any statistic named `%s'", pcstat_vars[i]);

      /* stat must be an integral type */
      if (stat->sc != sc_int && stat->sc != sc_uint && stat->sc != sc_counter)
	fatal("`-pcstat' statistical variable `%s' is not an integral type",
	      stat->name);

      /* register this stat */
      pcstat_stats[i] = stat;
      pcstat_lastvals[i] = STATVAL(stat);

      /* declare the sparce text distribution */
      sprintf(buf, "%s_by_pc", stat->name);
      sprintf(buf1, "%s (by text address)", stat->desc);
      pcstat_sdists[i] = stat_reg_sdist(sdb, buf, buf1,
					/* initial value */0,
					/* print fmt */(PF_COUNT|PF_PDF),
					/* format */"0x%p %u %.2f",
					/* print fn */NULL);
    }
  ld_reg_stats(sdb);
  mem_reg_stats(mem, sdb);
}
コード例 #3
0
ファイル: sim-profile.c プロジェクト: palmerc/lab
/* register simulator-specific statistics */
void
sim_reg_stats(struct stat_sdb_t *sdb)
{
  int i;

  stat_reg_counter(sdb, "sim_num_insn",
		   "total number of instructions executed",
		   &sim_num_insn, sim_num_insn, NULL);
  stat_reg_counter(sdb, "sim_num_refs",
		   "total number of loads and stores executed",
		   &sim_num_refs, 0, NULL);
  stat_reg_int(sdb, "sim_elapsed_time",
	       "total simulation time in seconds",
	       &sim_elapsed_time, 0, NULL);
  stat_reg_formula(sdb, "sim_inst_rate",
		   "simulation speed (in insts/sec)",
		   "sim_num_insn / sim_elapsed_time", NULL);

  if (prof_ic)
    {
      /* instruction class profile */
      ic_prof = stat_reg_dist(sdb, "sim_inst_class_prof",
			      "instruction class profile",
			      /* initial value */0,
			      /* array size */ic_NUM,
			      /* bucket size */1,
			      /* print format */(PF_COUNT|PF_PDF),
			      /* format */NULL,
			      /* index map */inst_class_str,
			      /* print fn */NULL);
    }

  if (prof_inst)
    {
      int i;
      char buf[512];

      /* conjure up appropriate instruction description strings */
      for (i=0; i < /* skip NA */OP_MAX-1; i++)
	{
	  sprintf(buf, "%-8s %-6s", md_op2name[i+1], md_op2format[i+1]);
	  inst_str[i] = mystrdup(buf);
	}
      
      /* instruction profile */
      inst_prof = stat_reg_dist(sdb, "sim_inst_prof",
				"instruction profile",
				/* initial value */0,
				/* array size */ /* skip NA */OP_MAX-1,
				/* bucket size */1,
				/* print format */(PF_COUNT|PF_PDF),
				/* format */NULL,
				/* index map */inst_str,
				/* print fn */NULL);
    }

  if (prof_bc)
    {
      /* instruction branch profile */
      bc_prof = stat_reg_dist(sdb, "sim_branch_prof",
			      "branch instruction profile",
			      /* initial value */0,
			      /* array size */bc_NUM,
			      /* bucket size */1,
			      /* print format */(PF_COUNT|PF_PDF),
			      /* format */NULL,
			      /* index map */branch_class_str,
			      /* print fn */NULL);
    }

  if (prof_am)
    {
      /* instruction branch profile */
      am_prof = stat_reg_dist(sdb, "sim_addr_mode_prof",
			      "addressing mode profile",
			      /* initial value */0,
			      /* array size */md_amode_NUM,
			      /* bucket size */1,
			      /* print format */(PF_COUNT|PF_PDF),
			      /* format */NULL,
			      /* index map */md_amode_str,
			      /* print fn */NULL);
    }

  if (prof_seg)
    {
      /* instruction branch profile */
      seg_prof = stat_reg_dist(sdb, "sim_addr_seg_prof",
			       "load/store address segment profile",
			       /* initial value */0,
			       /* array size */seg_NUM,
			       /* bucket size */1,
			       /* print format */(PF_COUNT|PF_PDF),
			       /* format */NULL,
			       /* index map */addr_seg_str,
			       /* print fn */NULL);
    }

  if (prof_tsyms && sym_ntextsyms != 0)
    {
      int i;

      /* load program symbols */
      sym_loadsyms(ld_prog_fname, load_locals);

      /* conjure up appropriate instruction description strings */
      tsym_names = (char **)calloc(sym_ntextsyms, sizeof(char *));

      for (i=0; i < sym_ntextsyms; i++)
	tsym_names[i] = sym_textsyms[i]->name;
      
      /* text symbol profile */
      tsym_prof = stat_reg_dist(sdb, "sim_text_sym_prof",
				"text symbol profile",
				/* initial value */0,
				/* array size */sym_ntextsyms,
				/* bucket size */1,
				/* print format */(PF_COUNT|PF_PDF),
				/* format */NULL,
				/* index map */tsym_names,
				/* print fn */NULL);
    }

  if (prof_dsyms && sym_ndatasyms != 0)
    {
      int i;

      /* load program symbols */
      sym_loadsyms(ld_prog_fname, load_locals);

      /* conjure up appropriate instruction description strings */
      dsym_names = (char **)calloc(sym_ndatasyms, sizeof(char *));

      for (i=0; i < sym_ndatasyms; i++)
	dsym_names[i] = sym_datasyms[i]->name;
      
      /* data symbol profile */
      dsym_prof = stat_reg_dist(sdb, "sim_data_sym_prof",
				"data symbol profile",
				/* initial value */0,
				/* array size */sym_ndatasyms,
				/* bucket size */1,
				/* print format */(PF_COUNT|PF_PDF),
				/* format */NULL,
				/* index map */dsym_names,
				/* print fn */NULL);
    }

  if (prof_taddr)
    {
      /* text address profile (sparse profile), NOTE: a dense print format
         is used, its more difficult to read, but the profiles are *much*
	 smaller, I've assumed that the profiles are read by programs, at
	 least for your sake I hope this is the case!! */
      taddr_prof = stat_reg_sdist(sdb, "sim_text_addr_prof",
				  "text address profile",
				  /* initial value */0,
				  /* print format */(PF_COUNT|PF_PDF),
				  /* format */"0x%p %u %.2f",
				  /* print fn */NULL);
    }

  for (i=0; i<pcstat_nelt; i++)
    {
      char buf[512], buf1[512];
      struct stat_stat_t *stat;

      /* track the named statistical variable by text address */

      /* find it... */
      stat = stat_find_stat(sdb, pcstat_vars[i]);
      if (!stat)
	fatal("cannot locate any statistic named `%s'", pcstat_vars[i]);

      /* stat must be an integral type */
      if (stat->sc != sc_int && stat->sc != sc_uint && stat->sc != sc_counter)
	fatal("`-pcstat' statistical variable `%s' is not an integral type",
	      stat->name);

      /* register this stat */
      pcstat_stats[i] = stat;
      pcstat_lastvals[i] = STATVAL(stat);

      /* declare the sparce text distribution */
      sprintf(buf, "%s_by_pc", stat->name);
      sprintf(buf1, "%s (by text address)", stat->desc);
      pcstat_sdists[i] = stat_reg_sdist(sdb, buf, buf1,
					/* initial value */0,
					/* print format */(PF_COUNT|PF_PDF),
					/* format */"0x%p %u %.2f",
					/* print fn */NULL);
    }
  ld_reg_stats(sdb);
  mem_reg_stats(mem, sdb);
}
コード例 #4
0
ファイル: sim-profile.c プロジェクト: palmerc/lab
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  int i;
  md_inst_t inst;
  register md_addr_t addr;
  register int is_write;
  enum md_opcode op;
  unsigned int flags;
  enum md_fault_type fault;

  fprintf(stderr, "sim: ** starting functional simulation **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t));

      if (verbose)
	{
	  myfprintf(stderr, "%10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
	  md_print_insn(inst, regs.regs_PC, stderr);
	  fprintf(stderr, "\n");
	  /* fflush(stderr); */
	}

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)		\
	case OP:							\
          SYMCAT(OP,_IMPL);						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "machine.def"
	default:
	  panic("attempted to execute a bogus opcode");
      }

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      /*
       * profile this instruction
       */
      flags = MD_OP_FLAGS(op);

      if (prof_ic)
	{
	  enum inst_class_t ic;

	  /* compute instruction class */
	  if (flags & F_LOAD)
	    ic = ic_load;
	  else if (flags & F_STORE)
	    ic = ic_store;
	  else if (flags & F_UNCOND)
	    ic = ic_uncond;
	  else if (flags & F_COND)
	    ic = ic_cond;      
	  else if (flags & F_ICOMP)
	    ic = ic_icomp;
	  else if (flags & F_FCOMP)
	    ic = ic_fcomp;
	  else if (flags & F_TRAP)
	    ic = ic_trap;
	  else
	    panic("instruction has no class");

	  /* update instruction class profile */
	  stat_add_sample(ic_prof, (int)ic);
	}

      if (prof_inst)
	{
	  /* update instruction profile */
	  stat_add_sample(inst_prof, (int)op - /* skip NA */1);
	}

      if (prof_bc)
	{
	  enum branch_class_t bc;

	  /* compute instruction class */
	  if (flags & F_CTRL)
	    {
	      if ((flags & (F_CALL|F_DIRJMP)) == (F_CALL|F_DIRJMP))
		bc = bc_call_dir;
	      else if ((flags & (F_CALL|F_INDIRJMP)) == (F_CALL|F_INDIRJMP))
		bc = bc_call_indir;
	      else if ((flags & (F_UNCOND|F_DIRJMP)) == (F_UNCOND|F_DIRJMP))
		bc = bc_uncond_dir;
	      else if ((flags & (F_UNCOND|F_INDIRJMP))== (F_UNCOND|F_INDIRJMP))
		bc = bc_uncond_indir;
	      else if ((flags & (F_COND|F_DIRJMP)) == (F_COND|F_DIRJMP))
		bc = bc_cond_dir;
	      else if ((flags & (F_COND|F_INDIRJMP)) == (F_COND|F_INDIRJMP))
		bc = bc_cond_indir;
	      else
		panic("branch has no class");

	      /* update instruction class profile */
	      stat_add_sample(bc_prof, (int)bc);
	    }
	}

      if (prof_am)
	{
	  enum md_amode_type am;

	  /* update addressing mode pre-probe FSM */
	  MD_AMODE_PREPROBE(op, fsm);

	  /* compute addressing mode */
	  if (flags & F_MEM)
	    {
	      /* compute addressing mode */
	      MD_AMODE_PROBE(am, op, fsm);

	      /* update the addressing mode profile */
	      stat_add_sample(am_prof, (int)am);

	      /* addressing mode pre-probe FSM, after all loads and stores */
	      MD_AMODE_POSTPROBE(fsm);
	    }
	}

      if (prof_seg)
	{
	  if (flags & F_MEM)
	    {
	      /* update instruction profile */
	      stat_add_sample(seg_prof, (int)bind_to_seg(addr));
	    }
	}

      if (prof_tsyms)
	{
	  int tindex;

	  /* attempt to bind inst address to a text segment symbol */
	  sym_bind_addr(regs.regs_PC, &tindex, /* !exact */FALSE, sdb_text);

	  if (tindex >= 0)
	    {
	      if (tindex > sym_ntextsyms)
		panic("bogus text symbol index");

	      stat_add_sample(tsym_prof, tindex);
	    }
	  /* else, could not bind to a symbol */
	}

      if (prof_dsyms)
	{
	  int dindex;

	  if (flags & F_MEM)
	    {
	      /* attempt to bind inst address to a text segment symbol */
	      sym_bind_addr(addr, &dindex, /* !exact */FALSE, sdb_data);

	      if (dindex >= 0)
		{
		  if (dindex > sym_ndatasyms)
		    panic("bogus data symbol index");

		  stat_add_sample(dsym_prof, dindex);
		}
	      /* else, could not bind to a symbol */
	    }
	}

      if (prof_taddr)
	{
	  /* add regs_PC exec event to text address profile */
	  stat_add_sample(taddr_prof, regs.regs_PC);
	}

      /* update any stats tracked by PC */
      for (i=0; i<pcstat_nelt; i++)
	{
	  counter_t newval;
	  int delta;

	  /* check if any tracked stats changed */
	  newval = STATVAL(pcstat_stats[i]);
	  delta = newval - pcstat_lastvals[i];
	  if (delta != 0)
	    {
	      stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta);
	      pcstat_lastvals[i] = newval;
	    }

	}

      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}
コード例 #5
0
ファイル: ssdp.cpp プロジェクト: baz/upnpx
int SSDP::Start(){
	int ret = 0;
	u32 optval = 0;
	
	if(mMulticastSocket != INVALID_SOCKET || mUnicastSocket != INVALID_SOCKET){
		ret = -9;
		goto EXIT;
	}
    
    //
	//Setup the Multicast Socket
    //
	mMulticastSocket = socket(PF_INET, SOCK_DGRAM, 0);
	STATNVAL(mMulticastSocket, INVALID_SOCKET, EXIT);
	
	//Set nonblocking
	optval = fcntl( mMulticastSocket, F_GETFL, 0 );
	STATNVAL(optval, -1,  CLEAN_AND_EXIT);
	ret = fcntl(mMulticastSocket, F_SETFL, optval | O_NONBLOCK);
	STATNVAL(ret, -1,  CLEAN_AND_EXIT);
	
	//Source address
	mSrcaddr.sin_family = PF_INET;
	mSrcaddr.sin_port = 0; //Let the IP stack decide 
	mSrcaddr.sin_addr.s_addr = INADDR_ANY; //Default multicast nic 

	//Reuse port
	optval = 1;
	ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	optval = 1;
	ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	

	//Disable loopback
	optval = 0;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&optval, sizeof(int));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	//TTL
	optval = mTTL;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&optval, sizeof(int));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	
	//Add membership
	mMreq.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mMreq.imr_interface.s_addr = INADDR_ANY;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreq, sizeof(struct ip_mreq));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	
	//Bind to all interface(s)
	ret = bind(mMulticastSocket, (struct sockaddr*)&mSrcaddr, sizeof(struct sockaddr));
	if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
		printf("address in use\n");
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	
	
	//Destination address
	mDstaddr.sin_family = PF_INET;
	mDstaddr.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mDstaddr.sin_port = htons(SSDP_MCAST_PORT);
	
    
    //
    // Setup the Unicast Socket (We listen for Advertisements)
    //
	mUnicastSocket = socket(PF_INET, SOCK_DGRAM, 0);
	STATNVAL(mUnicastSocket, INVALID_SOCKET, EXIT);
	
	//Set nonblocking
	optval = fcntl( mUnicastSocket, F_GETFL, 0 );
	STATNVAL(optval, -1,  CLEAN_AND_EXIT);
	ret = fcntl(mUnicastSocket, F_SETFL, optval | O_NONBLOCK);
	STATNVAL(ret, -1,  CLEAN_AND_EXIT);

    //Source address
	mUnicastSrcaddr.sin_family = PF_INET;
	mUnicastSrcaddr.sin_port = htons(SSDP_MCAST_PORT); 
	mUnicastSrcaddr.sin_addr.s_addr = INADDR_ANY; //Default nic 
    
	//Reuse port
	optval = 1;
	ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	optval = 1;
	ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);

    //Join Multicast group
    mMreqU.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mMreqU.imr_interface.s_addr = INADDR_ANY;
	ret = setsockopt(mUnicastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreqU, sizeof(struct ip_mreq));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	

    
    
	//Bind to all interface(s)
	ret = bind(mUnicastSocket, (struct sockaddr*)&mUnicastSrcaddr, sizeof(struct sockaddr));
	if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
		printf("address in use\n");
	STATVAL(ret, 0, CLEAN_AND_EXIT);
    
    

	//Start the read thread
	pthread_attr_t  attr;
	ret = pthread_attr_init(&attr);
	if(ret != 0){
		goto CLEAN_AND_EXIT;
	}
	ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if(ret != 0){
		pthread_attr_destroy(&attr);
		goto CLEAN_AND_EXIT;
	}
	
	ret = pthread_create(&mReadThread, &attr, SSDP::sReadLoop, (void*)this);
	
	pthread_attr_destroy(&attr);
	
	
	goto EXIT;
	
	
CLEAN_AND_EXIT:	
	close(mMulticastSocket);
	mMulticastSocket = INVALID_SOCKET;
	close(mUnicastSocket);
	mUnicastSocket = INVALID_SOCKET;

EXIT:	
	return ret;
}